Skip to content

Object.assign(this, ...) does not work as expected in ES2020/ES2021 but works in ES2022 target #9296

Closed as not planned
@arabold

Description

@arabold

Describe the bug

When defining DTOs, i.e. for NestJs, I'm often using Object.assign(this, ...) in the constructor of the class to quickly assign all properties to the newly created instance. When testing I found that the behavior between generating ES2020 and ES2022 differs unexpectedly.

The code below is an example for something that works as expected in ES2022 but does result in a different result in ES2021:

Input code

class Foo {
  value1: string;

  constructor(partial?: Partial<Foo>) {
    Object.assign(this, partial);
  }
}

class Bar extends Foo {
  value2: string;

  constructor(partial?: Partial<Bar>) {
    super(partial);
  }
}

const foo = new Foo({ value1: 'test1a' });
const bar = new Bar({ value1: 'test1b', value2: 'test2' });

console.log("foo =", foo);
console.log("bar =", bar);

Config

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "decorators": true
    },
    "transform": {
      "legacyDecorator": true,
      "decoratorMetadata": true
    },
    "target": "es2021"
  },
  "module": {
    "type": "commonjs"
  },
  "minify": false,
  "isModule": true
}

Playground link (or link to the minimal reproduction)

https://play.swc.rs/?version=1.7.0&code=H4sIAAAAAAAAA5WPSw6DIBCG95xi4kZMjIkutY%2Bki27bKyCl1oaAAWybGO%2FeEQxp2lVXwPyPb%2BCSWQtHrWEiAA8mR1HWYJ3pVdcQHHGt8DVypw0dmHE9k%2FsazuG2weAu81GAU3sX3BXY13eKultvc1gTWYOOmcyEcM87MAPi5YS6fLGrP9hYEtl2HET0fNCWArgiYQtKPBcWneIvUyesK1kKMyaCtcXFghXbf6xtmsc1%2FaQKWR%2FWUhRSdzTxuCRfsGtvlHw9Snii9Aaqi7edfAEAAA%3D%3D&config=H4sIAAAAAAAAA22PPQ6DMAyFd04Ree6AGDt35RBWMCiI%2FMg2UiPE3RsotEjtZvt779leKmNgFAt3s5SyNAlZiD99mUgOis8yAc2JxLJLCreTdmQjo0aWolCeaQfrm4MyBukj%2B2vgRAPa%2FDiNh%2B83sSXFDhX%2FBiMPpNtRJE3d1FAdDHzs5om%2BD21HbzobvY9hlIvSBdfnwnqcZN8PTtrTvq9cX2xFm%2B0hAQAA

SWC Info output

No response

Expected behavior

The expected console output is:

"foo =", {
  value1: "test1a"
}
"bar =", {
  constructor: function Bar(partial) {
        return _super.call(this, partial) || this;
    },
  value1: "test1b",
  value2: "test2"
}

value2 should be set to test2.

Actual behavior

When running with ES2020 or ES2021 as a target the output will instead be:

"foo =", {
  value1: "test1a"
}
"bar =", {
  constructor: function Bar(partial) {
        var _this = _super.call(this, partial) || this;
        _define_property(_this, "value2", void 0);
        return _this;
    },
  value1: "test1b",
  value2: undefined
}

In this case value2 is NOT set. To my understanding that is wrong. I validated this behavior with pure JS as well as TSC and in both cases value2 was set. The code generated by SWC does NOT set value2 correctly.

value2 is set when using ES2022 as target.

Version

1.7.0

Additional context

No response

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions