swc-project/swc · error

destructuring pattern inside TsParameterProperty

Error message

destructuring pattern inside TsParameterProperty

What it means

The TypeScript strip transform lowers parameter properties (`constructor(private a)`) into field declarations plus `this.a = a` assignments. It only supports identifier parameters: a TsParamPropParam::Assign whose left side is not Pat::Ident — i.e. a binding pattern like `constructor(private [a, b] = pair)` — is rejected as `destructuring pattern inside TsParameterProperty`. TypeScript itself forbids binding patterns in parameter properties, so valid parsed TS never reaches this.

Source

Thrown at crates/swc_ecma_transforms_typescript/src/transform.rs:266

                    let (pat, expr, id) = match param {
                        TsParamPropParam::Ident(binding_ident) => {
                            let id = binding_ident.to_id();
                            let prop_name = PropName::Ident(IdentName::from(&*binding_ident));
                            let mut value_ident = Ident::from(&*binding_ident);
                            value_ident.optional = false;
                            let value = value_ident.into();

                            (
                                binding_ident.clone().into(),
                                assign_value_to_this_prop(prop_name, value),
                                id,
                            )
                        }
                        TsParamPropParam::Assign(assign_pat) => {
                            let AssignPat { left, .. } = &assign_pat;

                            let Pat::Ident(binding_ident) = &**left else {
                                unreachable!("destructuring pattern inside TsParameterProperty");
                            };

                            let id = binding_ident.id.to_id();
                            let prop_name = PropName::Ident(binding_ident.id.clone().into());
                            let mut value_ident = binding_ident.id.clone();
                            value_ident.optional = false;
                            let value = value_ident.into();

                            (
                                assign_pat.clone().into(),
                                assign_value_to_this_prop(prop_name, value),
                                id,
                            )
                        }
                        #[cfg(swc_ast_unknown)]
                        _ => panic!("unable to access unknown nodes"),
                    };

View on GitHub (pinned to 5176682b65)

Solutions

  1. Fix the input: use identifier parameters and destructure inside the constructor body.
  2. Validate TsParamPropParam shapes before running swc_ecma_transforms_typescript (see type guard).
  3. Report to the tool that produced parameter properties with binding patterns.

Example fix

// before: binding pattern in a parameter property (invalid TS)
class C {
  constructor(private [a, b] = pair) {}
}

// after: identifier parameter property + destructuring in body
class C {
  private a; private b;
  constructor(pair = [1, 2]) { ([this.a, this.b] = pair); }
}
Defensive patterns

Strategy: type-guard

Validate before calling

use swc_ecma_ast::{Pat, TsParamPropParam};
fn param_props_ok(p: &TsParamPropParam) -> bool {
    match p {
        TsParamPropParam::Ident(_) => true,
        TsParamPropParam::Assign(a) => matches!(&*a.left, Pat::Ident(_)),
    }
}
// run over every Constructor param before the TS strip transform

Type guard

fn is_supported_param_prop(p: &TsParamPropParam) -> bool {
    match p {
        TsParamPropParam::Ident(_) => true,
        TsParamPropParam::Assign(a) => matches!(&*a.left, Pat::Ident(_)),
    }
}

Prevention

When it happens

Trigger: A parameter property declared with an array/object binding pattern — invalid TypeScript that nonetheless exists in the AST because it was built programmatically, parsed with a lenient/foreign parser, or mutated by a transform before the TS strip pass.

Common situations: AST generators and codemods synthesizing TS classes; estree/babel ASTs converted into swc ASTs; downleveling pipelines that accept non-tsc-validated input.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/27a1ecf59d9b9767. Report an issue: GitHub.