You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
useDefineForClassFields defaults to true in 4.2.4 #45584
JS output includes class fields (as if useDefineForClassFields was set to true) in VS2019+TS 4.2.4
JS output does not include class fields (as if useDefineForClassFields was set to false) in tsc 3.7 or 4.3
🙂 Expected behaviour
JS output should not include class fields unless useDefineForClassFields is explicitly set to true.
Whatever default useDefineForClassFields setting is should be consistent between tsc and VS2019+TS
The default of useDefineForClassFields depends on your target. For ESNext or ES2020 and above it defaults to true, which is the desired behaviour (to align with the ECMAScript standard).
Same code compiles in VS Code and command lines, it breaks in Visual Studio 2019+Typescript 4.2.4 only
This is very unlikely. You either use different versions and/or different TypeScript settings. The default for target is ES3, for which useDefineForClassFields defaults to false.
Martin Johns (@MartinJohns) target is the same as tsconfig.json and all TS source is the same in all environments. The setting is "target": "esnext".
VS Code running 4.3.5 with "target": "esnext" and useDefineForClassFields missing does not emit class fields.
VS2019 running 4.2.4 with the exact same settings and code does emit class fields.
Previous versions of Typescript in both VS Code and VS2019 consistently did not emit class fields, also with the same settings.
Setting "useDefineForClassFields": false makes the output consistent.
Whatever default of useDefineForClassFields is (though it should error with experimentalDecorators if it is intentionally incompatible with them) it should be consistent between TS versions or listed as a breaking change.
Please show a repro in the playground or with tsc. Talking about compiling with VS / VS Code leaves too much room for confusion. I just double checked with tsc and everything looks expected.
Andrii Dieiev (@IllusionMH) ah, thank you! I bet that’s what Keith Henry (@KeithHenry) is talking about. The examples I tested all had initializers. It’s a little hard to repro something without a code snippet 😅
The bug appears to only be in the weird embedded version of TypeScript that Visual Studio runs.
Andrii Dieiev (@IllusionMH) Part of what made this so hard for my team was that tsc on the command line worked with the same tsconfig file, so whenever we tried to isolate the TS build step from VS the problem just went away. It works just fine without useDefineForClassFields set at all, even when "target": "esnext" and on 4.3.5
Is #42663 working right? Is this actually a bug in 4.3? It was the inconsistency that made this hard to bugfix, if 4.3 should default "useDefineForClassFields": true then it doesn't appear to be.
I don't know anything about VS2019 and especially if it uses built-in TS version or one from node_modules when building.
For VS Code it's recommended to use Workspace Version of TS "typescript.tsdk": "node_modules\\typescript\\lib", to have same experience in tsc and errors in file.
And default build task (auto detected) would use TS from local node_modules.
VS Code running 4.3.5 with "target": "esnext" and useDefineForClassFields missing does not emit class fields.
output will be as expected (implied enabled useDefineForClassFields)
classMyClass{myField;}
If VS Code is not configured to use workspace version and in the same time shows 4.3.5 (which is provided with VS Code 1.59.1) in status bar - I would assume that there is chance that globally installed TS version is used for compilation and it's not 4.3.5.
Having simple repo with proper setup (TS in dependencies/devDependencies, tsconfig.json with "target": "esnext") that demonstrates problem will be helpful.
UPD.
DetailsAlso not reproduced class fields emit in 4.2.4
$ npx tsc -v
Version 4.2.4
$ cat main.js
cat: main.js: No such file or directory
$ cat main.ts
class MyClass {
myField: any;
}
$ npx tsc
$ cat main.js
class MyClass {
}
$ cat tsconfig.json
{
"compilerOptions": {
"target": "esnext"
},
"include": [
"*.ts"
]
}
We're starting to see this break Lit projects. useDefineForClassFields defaulting to true is a big breaking change for decorators and should not have been done lightly. Combined with TypeScript not following semver, npm users can very easily accidentally upgrade their versions to TypeScript and have severly broken applications because of this.
At the very least decorated fields should not emit native class fields because there is no way to metaprogram over them and the vast majority of decorators will break.
I’m closing this issue because it’s causing confusion—the title is a false assertion and leaving it open may lead people to believe it’s true. If you believe there’s a bug, please read through #45076 first, then open a new issue that clearly demonstrates the problem in a reproduceable way (demonstrated with tsc and/or the playground), following the issue template, including code samples or a link to a repository if necessary. If other tools, be they editors or external build systems, are required to demonstrate a problem with TypeScript’s emitted JS, it’s not a TypeScript bug. Thanks!
The default of useDefineForClassFields depends on your target. For ESNext or ES2020 and above it defaults to true, which is the desired behaviour (to align with the ECMAScript standard).
Are you closing this because useDefineForClassFieldsshould default to true when target is ESNext ?
Martin Johns (@MartinJohns) apologies, it was a bank holiday over here in the UK and when I came back the issue was closed, there didn't seem much point working on reproducing the problem when the response was that it's by design, just undocumented.
Activity
MartinJohns commentedon Aug 26, 2021
The default of
useDefineForClassFieldsdepends on your target. ForESNextorES2020and above it defaults totrue, which is the desired behaviour (to align with the ECMAScript standard).This is very unlikely. You either use different versions and/or different TypeScript settings. The default for
targetisES3, for whichuseDefineForClassFieldsdefaults tofalse.KeithHenry commentedon Aug 26, 2021
Martin Johns (@MartinJohns) target is the same as
tsconfig.jsonand all TS source is the same in all environments. The setting is"target": "esnext".VS Code running 4.3.5 with
"target": "esnext"anduseDefineForClassFieldsmissing does not emit class fields.VS2019 running 4.2.4 with the exact same settings and code does emit class fields.
Previous versions of Typescript in both VS Code and VS2019 consistently did not emit class fields, also with the same settings.
Setting
"useDefineForClassFields": falsemakes the output consistent.Whatever default of
useDefineForClassFieldsis (though it should error withexperimentalDecoratorsif it is intentionally incompatible with them) it should be consistent between TS versions or listed as a breaking change.andrewbranch commentedon Aug 26, 2021
Please show a repro in the playground or with
tsc. Talking about compiling with VS / VS Code leaves too much room for confusion. I just double checked with tsc and everything looks expected.IllusionMH commentedon Aug 26, 2021
There is issue that (I guess) should track docs for this change - #45076
andrewbranch commentedon Aug 26, 2021
Andrii Dieiev (@IllusionMH) ah, thank you! I bet that’s what Keith Henry (@KeithHenry) is talking about. The examples I tested all had initializers. It’s a little hard to repro something without a code snippet 😅
KeithHenry commentedon Aug 26, 2021
Andrew Branch (@andrewbranch) it works just fine in a playground or
tscon the command line.The bug appears to only be in the weird embedded version of TypeScript that Visual Studio runs.
Andrii Dieiev (@IllusionMH) Part of what made this so hard for my team was that
tscon the command line worked with the sametsconfigfile, so whenever we tried to isolate the TS build step from VS the problem just went away. It works just fine withoutuseDefineForClassFieldsset at all, even when"target": "esnext"and on 4.3.5Is #42663 working right? Is this actually a bug in 4.3? It was the inconsistency that made this hard to bugfix, if 4.3 should default
"useDefineForClassFields": truethen it doesn't appear to be.IllusionMH commentedon Aug 26, 2021
I don't know anything about VS2019 and especially if it uses built-in TS version or one from
node_moduleswhen building.For VS Code it's recommended to use Workspace Version of TS
"typescript.tsdk": "node_modules\\typescript\\lib",to have same experience intscand errors in file.And default build task (auto detected) would use TS from local
node_modules.I wasn't able to reproduce this
with next setup
{ "compilerOptions": { "target": "esnext" }, "include": [ "*.ts" ] }output will be as expected (implied enabled
useDefineForClassFields)If VS Code is not configured to use workspace version and in the same time shows 4.3.5 (which is provided with VS Code 1.59.1) in status bar - I would assume that there is chance that globally installed TS version is used for compilation and it's not 4.3.5.
Having simple repo with proper setup (TS in
dependencies/devDependencies,tsconfig.jsonwith"target": "esnext") that demonstrates problem will be helpful.UPD.
Details
Also not reproduced class fields emit in 4.2.4
justinfagnani commentedon Aug 27, 2021
We're starting to see this break Lit projects.
useDefineForClassFieldsdefaulting totrueis a big breaking change for decorators and should not have been done lightly. Combined with TypeScript not following semver, npm users can very easily accidentally upgrade their versions to TypeScript and have severly broken applications because of this.At the very least decorated fields should not emit native class fields because there is no way to metaprogram over them and the vast majority of decorators will break.
andrewbranch commentedon Aug 27, 2021
I’m closing this issue because it’s causing confusion—the title is a false assertion and leaving it open may lead people to believe it’s true. If you believe there’s a bug, please read through #45076 first, then open a new issue that clearly demonstrates the problem in a reproduceable way (demonstrated with tsc and/or the playground), following the issue template, including code samples or a link to a repository if necessary. If other tools, be they editors or external build systems, are required to demonstrate a problem with TypeScript’s emitted JS, it’s not a TypeScript bug. Thanks!
KeithHenry commentedon Aug 31, 2021
Andrew Branch (@andrewbranch) I'm a little confused by this:
My assertion is that
useDefineForClassFieldsdefaults totrue.However, Martin Johns (@MartinJohns) said:
Are you closing this because
useDefineForClassFieldsshould default totruewhentargetisESNext?tsc3.7 (which introduced it)tsc4.3.5tsc4.4.2true.Where is this breaking change documented? Should or shouldn't it default to true?
Assuming that this is desired behaviour and this is missing documentation I've raised #45653
MartinJohns commentedon Aug 31, 2021
Yes, it does. I just verified this behaviour.
The same result as Andrew had, and exactly why he asked you for a repro using tsc.
KeithHenry commentedon Aug 31, 2021
Martin Johns (@MartinJohns) apologies, it was a bank holiday over here in the UK and when I came back the issue was closed, there didn't seem much point working on reproducing the problem when the response was that it's by design, just undocumented.
justinfagnani commentedon Apr 22, 2022
We keep having users who have broken projects because of this. It's very frustrating.