Skip to content

Can SWC match TS emit for Parameter Properties? #9418

@robpalme

Description

@robpalme

Is there some config to get SWC to emit original authentic TS parameter properties?


I found that using TS parameter properties in SWC leads to JS emit that deviates from what TS produces and deviates from JS semantics. Specifically, when this TS feature is detected in a given class, SWC relocates all field initializers for that class into the constructor body.

Please note this is not about older JS versions or older TS modes. This is the behavior when not down-levelling and when ensuring useDefineForClassFields: true - which is enabled by default in TS when target: es2022 or target: esnext. So I'm asking about the most modern/minimal of output.

TypeScript Compilation

With tsc, field initializers are not relocated.

SourceTS emit
class TypeScriptParameterProperties {

    initializedField = this.pp;
    constructor(public pp: any) {

        console.log('finally');
    }
}
class TypeScriptParameterProperties {
    pp;
    initializedField = this.pp;
    constructor(pp) {
        this.pp = pp;
        console.log("finally");
    }
}

TS Playground link StackBlitz ilnk

SWC Compilation

With swc, field initializers are relocated into the constructor if (and only if) the class uses TS parameter properties.

SourceSWC emit
class TypeScriptParameterProperties {

    initializedField = this.pp;
    constructor(public pp: any) {


        console.log('finally');
    }
}
class TypeScriptParameterProperties {
    pp;
    initializedField;
    constructor(pp){
        this.pp = pp;
        this.initializedField = this.pp;
        console.log("finally");
    }
}

SWC Playground link

Conclusion

Based on history from @magic-akari it looks like this is intentional to have Swc-specific behavior. Which is Swc's choice to make - there is no spec or compliance test suite for this TS-specific feature.

For projects that want to preserve JS semantics and also want to match the official TypeScript output (e.g. in Node's experimental TS support), is there a way to do so? If not, then please consider this to be a polite feature request for a new mode, e.g. "jsc.transform.noInitializerRelocation"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions