swc-project/swc · error
ClassMember::{:?}
Error message
ClassMember::{:?} What it means
The non-legacy decorator transform builds a descriptors array from every class member. It handles `Method`, `PrivateMethod` and `ClassProp`, skips `Empty`/`TsIndexSignature`, and marks `Constructor` unreachable; all remaining members — private properties (`#x = 1`), static blocks, TS parameter properties, auto-accessors — hit `_ => unimplemented!("ClassMember::...")`. Because it iterates every member, the mere presence of such a member in a decorated class panics even if that member has no decorator.
Source
Thrown at crates/swc_ecma_transforms_proposal/src/decorators/mod.rs:557
span: DUMMY_SP,
arg: Some(value),
})],
}),
..Default::default()
}
.into(),
}),
_ => Prop::KeyValue(KeyValueProp {
key: PropName::Ident(quote_ident!("value")),
value: Expr::undefined(DUMMY_SP),
}),
}))))
.collect(),
}
.as_arg(),
)
}
_ => unimplemented!("ClassMember::{:?}", member,),
}
})
.map(Some)
.collect();
make_decorate_call(
class.decorators,
iter::once({
// function(_initialize) {}
Function {
span: DUMMY_SP,
params: iter::once(initialize.into())
.chain(super_class_ident.map(Pat::from))
.map(|pat| Param {
span: DUMMY_SP,
decorators: Vec::new(),
pat,View on GitHub (pinned to d7d7434666)
Solutions
- Switch to `jsc.transform.legacyDecorator: true` for classes that mix decorators with `#` fields or static blocks
- Replace `#x` private fields with plain (TS `private`) properties in decorated classes, and move static blocks out
- Reduce to a minimal repro and report upstream — extending the match arm in decorators/mod.rs is a tractable contribution
Example fix
// before
class C {
#count = 0;
@dec increment() { this.#count++; }
}
// after
class C {
private count = 0; // or legacyDecorator: true
@dec increment() { this.count++; }
} Defensive patterns
Strategy: validation
Validate before calling
// Rust: scan classes for unsupported members before the non-legacy decorator pass
fn class_has_unsupported_members(c: &Class) -> bool {
c.body.iter().any(|m| matches!(m,
ClassMember::PrivateProp(..) | ClassMember::StaticBlock(..) | ClassMember::TsParamProp(..)))
} Type guard
fn decorator_safe_member(m: &ClassMember) -> bool {
!matches!(m, ClassMember::PrivateProp(..) | ClassMember::StaticBlock(..) | ClassMember::TsParamProp(..))
} Prevention
- With modern decorators, keep decorated classes free of `#` fields, static blocks, and TS parameter properties
- Run a pre-scan on the AST and fall back to `legacyDecorator: true` per file when these members are present
When it happens
Trigger: Use modern (non-legacy) decorators on a class that also contains `#private` fields, `static { ... }` blocks, or TS constructor parameter properties.
Common situations: Decorator codebases that adopted `#` private state or static blocks before migrating off legacy decorators; Deno/TS-style classes mixing modern features; upgrading a legacy-decorator project that already used `#` fields.
Related errors
AI-assisted analysis of swc-project/swc@d7d7434666 (2026-08-16).
Data as JSON: /api/errors/38305c659aa554f8.
Report an issue: GitHub.