Repository navigation
useDefineForClassFields defaults to true in 4.2.4 #45584
Description
Activity
MartinJohns commented
on Aug 26, 2021 ContributorMore actionsThe default of
useDefineForClassFieldsdepends on your target. ForESNextorES2020and above it defaults totrue, 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
targetisES3, for whichuseDefineForClassFieldsdefaults tofalse.Reacted by Andrii DieievMartin 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 commented
on Aug 26, 2021 MemberMore actionsPlease 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.Reacted by Martin Johns- addedQuestionAn issue which isn't directly actionable in codeAn issue which isn't directly actionable in code
on Aug 26, 2021 IllusionMH commented
on Aug 26, 2021 ContributorMore actionsThere is issue that (I guess) should track docs for this change - #45076
andrewbranch commented
on Aug 26, 2021 MemberMore actionsAndrii 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 😅
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 commented
on Aug 26, 2021 ContributorMore actionsI 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.VS Code running 4.3.5 with "target": "esnext" and useDefineForClassFields missing does not emit class fields.
I wasn't able to reproduce this
with next setup
$ npx tsc -v Version 4.3.5class MyClass { myField: any; }
{ "compilerOptions": { "target": "esnext" }, "include": [ "*.ts" ] }output will be as expected (implied enabled
useDefineForClassFields)class MyClass { 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.jsonwith"target": "esnext") that demonstrates problem will be helpful.UPD.
Details
Also 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.
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.
Reacted by Keith Henryandrewbranch commented
on Aug 27, 2021 MemberMore actionsI’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!
Andrew Branch (@andrewbranch) I'm a little confused by this:
the title is a false assertion and leaving it open may lead people to believe it’s true
My assertion is that
useDefineForClassFieldsdefaults totrue.However, Martin Johns (@MartinJohns) said:
The default of
useDefineForClassFieldsdepends on your target. ForESNextorES2020and above it defaults totrue, which is the desired behaviour (to align with the ECMAScript standard).Are you closing this because
useDefineForClassFieldsshould default totruewhentargetisESNext?- It doesn't with
tsc3.7 (which introduced it) - It does with VS2019+Embedded Typescript 4.2.4
- It doesn't with
tsc4.3.5 - It now does with
tsc4.4.2 - According to Gh 41788 incorrect output for esprivate with nested class in esnext #42663 it should default to
true. - Which is what I'm asserting.
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
- It doesn't with
MartinJohns commented
on Aug 31, 2021 ContributorMore actionsIt doesn't with tsc 4.3.5
Yes, it does. I just verified this behaviour.
~/ ./node_modules/.bin/tsc --version Version 4.3.5 ~/ cat index.ts class Foo { member!: string; } ~/ ./node_modules/.bin/tsc --target es2019 index.ts && cat index.js class Foo { } ~/ ./node_modules/.bin/tsc --target esnext index.ts && cat index.js class Foo { member; }The same result as Andrew had, and exactly why he asked you for a repro using tsc.
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.
We keep having users who have broken projects because of this. It's very frustrating.
- locked as resolved and limited conversation to collaborators
on Oct 21, 2025
Bug Report
🔎 Search Terms
useDefineForClassFields🕗 Version & Regression Information
⏯ Playground Link
Same code compiles in VS Code and command lines, it breaks in Visual Studio 2019+Typescript 4.2.4 only
💻 Code
Use a
@decoratoron class properties or any code that is incompatible withuseDefineForClassFields: trueSomething like:
Do not include
useDefineForClassFieldsin yourtsconfig.jsonat all.Run Typescript compile.
When VS2019 with TS 4.2.4 compiles JS output includes class fields, something like:
When
tsc4.3.5 compiles for the sametsconfigand source files it doesn't include class fields, something like:Adding
useDefineForClassFields: falseworks around the issue and makes the JS output consistent.Property decorators are ignored (as per #35081).
🙁 Actual behaviour
JS output includes class fields (as if
useDefineForClassFieldswas set to true) in VS2019+TS 4.2.4JS output does not include class fields (as if
useDefineForClassFieldswas set to false) in tsc 3.7 or 4.3🙂 Expected behaviour
JS output should not include class fields unless
useDefineForClassFieldsis explicitly set to true.Whatever default
useDefineForClassFieldssetting is should be consistent between tsc and VS2019+TS