{"record":{"id":"d89f4f6697dbe49c","repo":"facebook/flow","slug":"records-can-only-have-identifier-method-keys","errorCode":null,"errorMessage":"Records can only have identifier method keys","messagePattern":"Records can only have identifier method keys","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_typing_statement/src/statement.rs","lineNumber":18901,"sourceCode":"                                                    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;\n                            let prop_loc = prop_loc.dupe();\n                            let default_value = default_value.as_ref();\n                            let prop_comments = prop_comments.clone();\n                            let (key_loc, name) =\n                                flow_parser_utils::record_utils::loc_and_string_of_property_key(\n                                    key,","sourceCodeStart":18883,"sourceCodeEnd":18919,"githubUrl":"https://github.com/facebook/flow/blob/5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9/rust_port/crates/flow_typing_statement/src/statement.rs#L18883-L18919","documentation":"Records require method keys to be plain identifiers. In the record body lowering, a method keyed by a StringLiteral, NumberLiteral, BigIntLiteral, or Computed expression panics — the record's structural typing relies on identifier names, so non-identifier keys are unrepresentable and crash the typer.","triggerScenarios":"Typechecking a record whose body contains a method with a quoted key ('quoted-name'() {}), a numeric key (42() {}), or a computed key ([expr]() {}) — any key form other than a bare identifier.","commonSituations":"Object-literal code pasted into a record (string keys are legal in objects); codemods converting objects to records verbatim; generated code using dynamic key names.","solutions":["Rename non-identifier method keys to valid identifiers.","If dynamic or quoted keys are required, use an object type or a class instead of a record.","Codemods: whitelist identifier keys only when emitting record bodies."],"exampleFix":"// before\nrecord Env {\n  'query-db'(): void { }\n  ['load' + 'er'](): void { }\n}\n\n// after: identifier keys only\nrecord Env {\n  queryDb(): void { }\n  loader(): void { }\n}","handlingStrategy":"validation","validationCode":"// lint before typechecking: record method keys must be identifiers\nfunction recordHasNonIdentifierKey(node) {\n  return node.body.some(\n    (el) => el.type === 'Method' && el.key.type !== 'Identifier'\n  );\n}\nif (recordHasNonIdentifierKey(recordNode)) reportError(recordNode, 'record method keys must be identifiers');","typeGuard":"function recordMemberAllowed(el) {\n  if (el.type === 'Property') return true;\n  if (el.type !== 'Method') return false;\n  return el.kind === 'method' && el.key.type === 'Identifier';\n}","tryCatchPattern":null,"preventionTips":["Rename quoted, numeric, and computed keys to identifiers before putting members in records.","Codemods converting object literals to records must whitelist identifier keys only.","Use object types or maps when string/dynamic keys are inherent to the data.","Cover the restriction in the record syntax lint rule so it fails in CI, not in the typer."],"tags":["flow","records","syntax","typing","object-keys","computed-keys"],"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-14T05:17:10.506Z"}