Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bad TS class translation #11605

Closed
pierreduot opened this issue Jun 4, 2024 · 4 comments
Closed

Bad TS class translation #11605

pierreduot opened this issue Jun 4, 2024 · 4 comments
Labels
bug Something isn't working needs triage

Comments

@pierreduot
Copy link

What version of Bun is running?

1.1.12

What platform is your computer?

Linux 5.15.0-107-generic x86_64 x86_64

What steps can reproduce the bug?

Considering following TS code:

abstract class Cparent {
    public parentVal: string;
    constructor() {
        this.parentVal = 'parent';
        this.init();
    }
    init() { }
}

class Achild extends Cparent {
    public childVal!: string;
    constructor() {
        super();
    }
    override init() {
        this.childVal = 'child';
    }
}

const a = new Achild();
console.log(a.parentVal, a.childVal);

What is the expected behavior?

Expected behavior when compiling with TS:

"use strict";
class Cparent {
    constructor() {
        this.parentVal = 'parent';
        this.init();
    }
    init() { }
}
class Achild extends Cparent {
    constructor() {
        super();
    }
    init() {
        this.childVal = 'child';
    }
}
const a = new Achild();
console.log(a.parentVal, a.childVal);

And when running:

"parent",  "child"

What do you see instead?

When building with bun:

// buntest.ts
class Cparent {
  parentVal;
  constructor() {
    this.parentVal = "parent";
    this.init();
  }
  init() {
  }
}

class Achild extends Cparent {
  childVal;
  constructor() {
    super();
  }
  init() {
    this.childVal = "child";
  }
}
var a = new Achild;
console.log(a.parentVal, a.childVal);

When running:

parent undefined

Additional information

No response

@pierreduot pierreduot added the bug Something isn't working label Jun 4, 2024
@codehz
Copy link
Contributor

codehz commented Jun 10, 2024

I think it is related to useDefineForClassFields in tsconfig.json
which is defaulted to true in ESNext
image
ref: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier
so the code should be compiled to:

"use strict";
class Cparent {
    parentVal;
    constructor() {
        this.parentVal = 'parent';
        this.init();
    }
    init() { }
}
class Achild extends Cparent {
    childVal;
    constructor() {
        super();
    }
    init() {
        this.childVal = 'child';
    }
}
const a = new Achild();
console.log(a.parentVal, a.childVal);

which will give you "parent", undefined

@pierreduot
Copy link
Author

If I set useDefineForClassFields, the result is :

"use strict";
class Cparent {
    constructor() {
        Object.defineProperty(this, "parentVal", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        this.parentVal = 'parent';
        this.init();
    }
    init() { }
}
class Achild extends Cparent {
    constructor() {
        super();
        Object.defineProperty(this, "childVal", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
    }
    init() {
        this.childVal = 'child';
    }
}
const a = new Achild();
console.log(a.parentVal, a.childVal);

And result is parent, undefined because childVal property is redifined after super().

But I think that the logical behavior should be this result : parent, child.
I'm right or not ?

@codehz
Copy link
Contributor

codehz commented Jun 10, 2024

check this microsoft/TypeScript#33509 it should be considered as correct behavior in spec...
if you don't like it, set useDefineForClassFields to false

@pierreduot
Copy link
Author

Thanks for the ref.
I understand the differences in behavior better.
In fact, I think the problem mainly comes from having the parent call the init function implemented in the child.
By writing differently, I would no longer have problems!
I can close the issue ! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs triage
Projects
None yet
Development

No branches or pull requests

3 participants