swc-project / swc

Rust-based platform for the Web
https://swc.rs
Apache License 2.0
31.26k stars 1.23k forks source link

Overriding type of class variable causes the variable to be reset #9751

Closed quantizor closed 1 day ago

quantizor commented 1 day ago

Describe the bug

When working with ES6 classes and extending an existing class, but updating the type of a class variable, the variable is reinitialized and should not be.

Input code

class Root {
  json: any;

  constructor({json}) {
    this.json = json
  }
}

export class PersonAccessor extends Root {
  json: string;

  checkJSON() {
    return this.json.startsWith('foo');
  }
}

"strictPropertyInitialization": false is set in tsconfig.json

Config

{
  "jsc": {
    "experimental": {
      "plugins": [
        [
          "@swc/plugin-styled-components",
          {
            "displayName": true
          }
        ]
      ]
    },
    "parser": {
      "syntax": "typescript",
      "tsx": true
    },
    "transform": {
      "react": {
        "runtime": "automatic"
      }
    }
  }
}

Playground link (or link to the minimal reproduction)

https://play.swc.rs/?version=1.3.101&code=H4sIAAAAAAAAA0utKMgvKlFIzkksLlYISC0qzs9zTE5OLS7OL1Ko5uVSUEiE8fISc1OtFIpLijLz0q1BMsn5eUBeaXJJfpEGsqQmRKOCQklGZrEeSEbBFqwbrKuWl6sWAHac7711AAAA&config=H4sIAAAAAAAAA2VQywqDQAy89ysk5xashR76Bb302vuyRtmyL5IIivjvXZ9Vektmksxk%2BlOWwYc1PLI%2BlamJihhp6xPCnRfVJgSki8iaTBQ4r6zwSFXKMm5YiTqQkkCcKKEGJ2KYeRBFNcp4D7nIi%2BtyC2wIjMvCAjnjTdXtzejgIiHzn6ZTvra4wkdBUp6rQG5%2FaPP4RmIT%2FOgnuSku%2BQ0O29gKklf2iTYi8U5hmgAXymYSXgIcQ5qfu8NvaH1kMw2GX%2BvmFNHwBf%2FIwMeMAQAA

SWC Info output

Operating System:
    Platform: darwin
    Arch: arm64
    Machine Type: arm64
    Version: Darwin Kernel Version 24.1.0: Thu Oct 10 21:03:11 PDT 2024; root:xnu-11215.41.3~2/RELEASE_ARM64_T6020
    CPU: (12 cores)
        Models: Apple M2 Pro

Binaries:
    Node: 20.18.0
    npm: 10.8.2
    Yarn: 4.3.1
    pnpm: N/A

Relevant Packages:
    @swc/core: 1.9.2
    @swc/helpers: 0.5.1
    @swc/types: 0.1.15
    typescript: 5.4.5

SWC Config:
    output: N/A
    .swcrc path: N/A

Next.js info:
    output: N/A

Expected behavior

Output:

function _define_property(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
class Root {
    constructor({ json }){
        _define_property(this, "json", void 0);
        this.json = json;
    }
}
export class PersonAccessor extends Root {
    checkJSON() {
        return this.json.startsWith('foo');
    }
    constructor(...args){
        super(...args);
    }
}

^ Note the lack of variable redefinition in PersonAccessor.constructor

Actual behavior

Output:

function _define_property(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
class Root {
    constructor({ json }){
        _define_property(this, "json", void 0);
        this.json = json;
    }
}
export class PersonAccessor extends Root {
    checkJSON() {
        return this.json.startsWith('foo');
    }
    constructor(...args){
        super(...args);
        _define_property(this, "json", void 0);
    }
}

Note _define_property(this, "json", void 0); coming after super(...args);, this should not be there, there is no override to the value of the class variable only a type override.

Version

1.9.2

Additional context

No response

kdy1 commented 1 day ago

https://swc.rs/docs/migrating-from-tsc#usedefineforclassfields

quantizor commented 1 day ago

https://swc.rs/docs/migrating-from-tsc#usedefineforclassfields

I actually tried that and didn't see a difference

kdy1 commented 1 day ago

https://play.swc.rs/?version=1.9.2&code=H4sIAAAAAAAAA2WPuw7CMAxF90r9B29Nln5Aqw6sDIBgYK6CoYUqRrErQFX%2BnSZVeY658fG5Nl3NDFsigSFNAM5MtoDaPso0CW9DlsX1RsipIXx6PQ0CSNNyHiKoIhZSnyY%2BgCau3aAb84UxyEwO8C5oD%2F%2B2UdDa0yxs0FyWu%2FVKvUQOpXf27ctZaie8b6VR2ZEo0%2BWXO1SGa3RXFm8%2FNaYzCoik1%2BWMUId5Ryc1gflHD%2F0EAm7hkiUBAAA%3D&config=H4sIAAAAAAAAA21QPWvDUAzc%2ByuM5hZSFzp0bQldunYXthxeeV%2FoZIgJ%2Be99duKXmHaTdNLd6U4PTUM%2F6OitOZWyNJkVorUvE0zR%2BFgmZFMWdOqy0eOKGmZoYA%2Bps166pGxJUSDTURbgfMHJWA9iM5%2Bg3bXPVy7yKUG2XBRcdMN076ZLIasAf0QDx4Ov91tF5Yghabgnqia%2FReFSnA0VO%2B3T7uX23Qj5kMFF2Sd99wzsnfge%2F6rI0UQj%2B0%2FxWXRjcFmhkPpxcXiNeo7zEsMr3ZbWj%2BsxOXytl0uY51%2B0PLyhtgEAAA%3D%3D

It works

quantizor commented 1 day ago

@kdy1 thank you, you are right. In my case webpack cache did not properly bust with the .swcrc change and I was seeing old results.

quantizor commented 1 day ago

@kdy1 one point of confusion, the flag only works if set in swc config and if you do it in tsconfig.json it is not picked up