facebook/flow · error
Records can only have identifier method keys
Error message
Records can only have identifier method keys
What it means
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.
Source
Thrown at rust_port/crates/flow_typing_statement/src/statement.rs:18901
func,
),
method_sig,
Some(set_asts),
Some(set_type),
&mut class_sig,
);
rev_elements.push(Box::new(get_element));
}
}
}
expression::object::Key::PrivateName(_) => {
panic!("Records cannot have private methods")
}
expression::object::Key::StringLiteral(_)
| expression::object::Key::NumberLiteral(_)
| expression::object::Key::BigIntLiteral(_)
| expression::object::Key::Computed(_) => {
panic!("Records can only have identifier method keys")
}
},
statement::record_declaration::BodyElement::Property(prop) => {
let statement::record_declaration::Property {
loc: prop_loc,
key,
annot,
default_value,
comments: prop_comments,
invalid_syntax: _,
} = prop;
let prop_loc = prop_loc.dupe();
let default_value = default_value.as_ref();
let prop_comments = prop_comments.clone();
let (key_loc, name) =
flow_parser_utils::record_utils::loc_and_string_of_property_key(
key,View on GitHub (pinned to 5c86586199)
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.
Example fix
// before
record Env {
'query-db'(): void { }
['load' + 'er'](): void { }
}
// after: identifier keys only
record Env {
queryDb(): void { }
loader(): void { }
} Defensive patterns
Strategy: validation
Validate before calling
// lint before typechecking: record method keys must be identifiers
function recordHasNonIdentifierKey(node) {
return node.body.some(
(el) => el.type === 'Method' && el.key.type !== 'Identifier'
);
}
if (recordHasNonIdentifierKey(recordNode)) reportError(recordNode, 'record method keys must be identifiers'); Type guard
function recordMemberAllowed(el) {
if (el.type === 'Property') return true;
if (el.type !== 'Method') return false;
return el.kind === 'method' && el.key.type === 'Identifier';
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Records cannot have constructors
- Records cannot have getters
- Records cannot have setters
- Records cannot have private methods
- Unexpected function parameter ${param.type}
AI-assisted analysis of facebook/flow@5c86586199 (2026-08-20).
Data as JSON: /api/errors/d89f4f6697dbe49c.
Report an issue: GitHub.