facebook/flow · error
Records cannot have setters
Error message
Records cannot have setters
What it means
The setter counterpart of the record restrictions: MethodKind::Set in a record body panics in the typing pass. Records are immutable data carriers in Flow's design, and a setter would imply mutable state, so the typer aborts rather than type it.
Source
Thrown at rust_port/crates/flow_typing_statement/src/statement.rs:18863
kind: kind_c,
static_: static_c,
override_: false,
ts_accessibility: None,
decorators: vec![].into(),
comments: method_comments_c,
},
))
};
match kind {
ast::class::MethodKind::Constructor => {
panic!("Records cannot have constructors")
}
ast::class::MethodKind::Get => {
panic!("Records cannot have getters")
}
ast::class::MethodKind::Set => {
panic!("Records cannot have setters")
}
ast::class::MethodKind::Method => {
check_duplicate_name(
&mut public_seen_names,
method_id_loc.dupe(),
&Name::new(name.dupe()),
static_,
false,
ClassMemberKind::ClassMemberMethod,
);
class_sig::add_method(
static_,
false,
false,
Name::new(name),
method_id_loc,
Some(func_loc),
static_View on GitHub (pinned to 5c86586199)
Solutions
- Remove the setter from the record body.
- Model updates functionally: function setN(c: Counter, v: number): Counter { return { ...c, n: v }; }.
- Use a class if in-place mutation is genuinely required.
- Reject setter members in record bodies via a lint/codemod check.
Example fix
// before
record Counter {
n: number;
set n(v: number) { this.n = v; }
}
// after: return a new record instead of mutating
record Counter { n: number; }
function setN(c: Counter, v: number): Counter { return { ...c, n: v }; } Defensive patterns
Strategy: validation
Validate before calling
// lint before typechecking: records must not contain setters
function recordHasSetter(node) {
return node.body.some((el) => el.type === 'Method' && el.kind === 'set');
}
if (recordHasSetter(recordNode)) reportError(recordNode, 'records cannot have setters'); 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
- Model record updates functionally: return a new record from a function instead of setting.
- Keep mutation in classes; do not port mutable classes to records.
- Include setter-in-record in the same lint rule set as the other record restrictions.
- Codemods: rewrite setters into update functions returning new records.
When it happens
Trigger: Typechecking a record declaration containing a setter — record Counter { n: number; set n(v: number) { ... } } — once the parser has admitted the member.
Common situations: Porting mutable classes to records without removing mutation; IDE refactorings generating setters; codemods that copy accessor pairs into record bodies.
Related errors
- Records cannot have constructors
- Records cannot have getters
- Records cannot have private methods
- Records can only have identifier method keys
- Unexpected function parameter ${param.type}
AI-assisted analysis of facebook/flow@5c86586199 (2026-08-20).
Data as JSON: /api/errors/4b670b65e235f11b.
Report an issue: GitHub.