{"record":{"id":"4fc8a6e3aafce605","repo":"facebook/flow","slug":"records-cannot-have-private-methods","errorCode":null,"errorMessage":"Records cannot have private methods","messagePattern":"Records cannot have private methods","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_typing_statement/src/statement.rs","lineNumber":18895,"sourceCode":"                                            false,\n                                            Name::new(name),\n                                            method_id_loc,\n                                            Some(func_loc),\n                                            static_\n                                                && flow_parser_utils::this_finder::function_uses_this(\n                                                    func,\n                                                ),\n                                            method_sig,\n                                            Some(set_asts),\n                                            Some(set_type),\n                                            &mut class_sig,\n                                        );\n                                        rev_elements.push(Box::new(get_element));\n                                    }\n                                }\n                            }\n                            expression::object::Key::PrivateName(_) => {\n                                panic!(\"Records cannot have private methods\")\n                            }\n                            expression::object::Key::StringLiteral(_)\n                            | expression::object::Key::NumberLiteral(_)\n                            | expression::object::Key::BigIntLiteral(_)\n                            | expression::object::Key::Computed(_) => {\n                                panic!(\"Records can only have identifier method keys\")\n                            }\n                        },\n\n                        statement::record_declaration::BodyElement::Property(prop) => {\n                            let statement::record_declaration::Property {\n                                loc: prop_loc,\n                                key,\n                                annot,\n                                default_value,\n                                comments: prop_comments,\n                                invalid_syntax: _,\n                            } = prop;","sourceCodeStart":18877,"sourceCodeEnd":18913,"githubUrl":"https://github.com/facebook/flow/blob/5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9/rust_port/crates/flow_typing_statement/src/statement.rs#L18877-L18913","documentation":"When lowering record body elements, a method keyed by Key::PrivateName (a #name member) hits an unconditional panic: records do not support private members. The typer has no representation for record-private methods, so this is a hard error in the typing pass.","triggerScenarios":"Typechecking a record whose body declares a #private field or method — record Counter { value: number; #reset() { ... } } — after the parser accepted the private-name key.","commonSituations":"Encapsulated-class patterns carried over into records; codemods preserving private helpers when converting classes; developers expecting class-private semantics inside records.","solutions":["Remove the #private member from the record body.","Move the helper out as a module-level function that takes the record as a parameter.","Use a class if private state is essential to the design.","Codemods: rewrite private members into free functions when emitting records."],"exampleFix":"// before\nrecord Counter {\n  value: number;\n  #reset() { }\n}\n\n// after: no private members; move the logic out\nrecord Counter { value: number; }\nfunction reset(c: Counter): Counter { return { value: 0 }; }","handlingStrategy":"validation","validationCode":"// lint before typechecking: records must not contain private members\nfunction recordHasPrivateMember(node) {\n  return node.body.some(\n    (el) => (el.type === 'Method' || el.type === 'Property') && el.key?.type === 'PrivateName'\n  );\n}\nif (recordHasPrivateMember(recordNode)) reportError(recordNode, 'records cannot have private members');","typeGuard":"function recordMemberAllowed(el) {\n  if (el.type === 'Property') return el.key.type === 'Identifier';\n  if (el.type !== 'Method') return false;\n  return el.kind === 'method' && el.key.type === 'Identifier';\n}","tryCatchPattern":null,"preventionTips":["Move private helpers out of records into module-level functions taking the record.","Use classes when private state is part of the design.","Extend the record lint rule to reject PrivateName keys of any member kind.","Check codemod output for #members when converting encapsulated classes."],"tags":["flow","records","syntax","typing","private-members"],"backgroundTag":"flow-record-syntax-error","analyzedSha":"5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9","analyzedAt":"2026-08-20T10:41:37.992Z","contentChangedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}