facebook/flow · error

Records cannot have private methods

Error message

Records cannot have private methods

What it means

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.

Source

Thrown at rust_port/crates/flow_typing_statement/src/statement.rs:18895

                                            false,
                                            Name::new(name),
                                            method_id_loc,
                                            Some(func_loc),
                                            static_
                                                && flow_parser_utils::this_finder::function_uses_this(
                                                    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;

View on GitHub (pinned to 5c86586199)

Solutions

  1. Remove the #private member from the record body.
  2. Move the helper out as a module-level function that takes the record as a parameter.
  3. Use a class if private state is essential to the design.
  4. Codemods: rewrite private members into free functions when emitting records.

Example fix

// before
record Counter {
  value: number;
  #reset() { }
}

// after: no private members; move the logic out
record Counter { value: number; }
function reset(c: Counter): Counter { return { value: 0 }; }
Defensive patterns

Strategy: validation

Validate before calling

// lint before typechecking: records must not contain private members
function recordHasPrivateMember(node) {
  return node.body.some(
    (el) => (el.type === 'Method' || el.type === 'Property') && el.key?.type === 'PrivateName'
  );
}
if (recordHasPrivateMember(recordNode)) reportError(recordNode, 'records cannot have private members');

Type guard

function recordMemberAllowed(el) {
  if (el.type === 'Property') return el.key.type === 'Identifier';
  if (el.type !== 'Method') return false;
  return el.kind === 'method' && el.key.type === 'Identifier';
}

Prevention

When it happens

Trigger: Typechecking a record whose body declares a #private field or method — record Counter { value: number; #reset() { ... } } — after the parser accepted the private-name key.

Common situations: Encapsulated-class patterns carried over into records; codemods preserving private helpers when converting classes; developers expecting class-private semantics inside records.

Related errors


AI-assisted analysis of facebook/flow@5c86586199 (2026-08-20). Data as JSON: /api/errors/4fc8a6e3aafce605. Report an issue: GitHub.