Handle breaking change in class property runtime behavior · Issue #27644 · microsoft/TypeScript (original) (raw)
From #12212 (comment) @joeywatts:
class A { property = 'some string'; } class B extends A { property; } const instanceB = new B(); // "some string" or "undefined" ? console.log(instanceB.property);
It appears from the current definition at https://github.com/tc39/proposal-class-fields that this code will print undefined
.
If the proposal advances further with these semantics, we'll need to figure out a mitigation strategy, preferably sooner rather than later.
One option is to make the code as written a type error for ~2 versions and force people to write an explicit = undefined
initializer, then remove the error.
Edit [@sandersn]:
Here is the current plan, together with what has happened so far.
TypeScript 3.6
- Allow accessors in ambient class declarations #32787: allow accessors like
declare class C { get p(): number; }
(andset
as well) - No changes to .js emit yet
- No changes to .d.ts emit yet
TypeScript 3.7
- Always emit accessors in .d.ts files #33470: emit get/set accessors in declaration files
- Disallow property/accessor overrides #33401: accessors may not override properties and vice versa.
- Disallow uninitialised property overrides #33423: uninitialised properties may not override properties.
- Introduce new syntax,
class C extends B { declare x: number }
- Introduce a codefix that inserts
declare
where needed. - This declaration is erased, like the original declaration in old versions of TS
- Introduce new syntax,
- Add useDefineForClassFields flag for Set -> Define property declaration #33509 Introduce a new flag,
useDefineForClassFields
.- When
"useDefineForClassFields": false
:
* Initialized fields in class bodies are emitted as constructor assignments (even when targeting ESNext).
* Uninitialized fields in class bodies are erased.
* The preceding errors are silenced. - When
"useDefineForClassFields": true
:
* Fields in class bodies are emitted as-is for ESNext.
* Fields in class bodies are emitted as Object.defineProperty assignments in the constructor otherwise. - In 3.7,
"useDefineForClassFields"
defaults tofalse
- Declaration emit is the same regardless of the flag's value.
- When
TypeScript 3.8
(or, the first version after class fields reaches Stage 4)
"useDefineForClassFields"
defaults to true when targetting ESNext.- issue new errors as suggestions with codefixes, even when
"useDefineForClassFields": false
.