Skip to content

Commit 13cddae

Browse files
authored
Allow references to uninitialized ambient properties (#36112)
Previously these were incorrectly treated just like normal properties: ```ts class Parent { a: any; constructor(arg: any) { this.a = arg; } } class Child extends Parent { declare a: number; constructor(arg: number) { super(arg); console.log(this.a); // Property 'a' is used before being assigned. (2565) } } ``` Fixes #35327
1 parent 357f715 commit 13cddae

File tree

6 files changed

+147
-1
lines changed

6 files changed

+147
-1
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23298,7 +23298,7 @@ namespace ts {
2329823298
const declaration = prop && prop.valueDeclaration;
2329923299
if (declaration && isInstancePropertyWithoutInitializer(declaration)) {
2330023300
const flowContainer = getControlFlowContainer(node);
23301-
if (flowContainer.kind === SyntaxKind.Constructor && flowContainer.parent === declaration.parent) {
23301+
if (flowContainer.kind === SyntaxKind.Constructor && flowContainer.parent === declaration.parent && !(declaration.flags & NodeFlags.Ambient)) {
2330223302
assumeUninitialized = true;
2330323303
}
2330423304
}

tests/baselines/reference/derivedUninitializedPropertyDeclaration.errors.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,19 @@ tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedP
8585
q!: 1 | 2 | 3 // ok, extends a property from an interface
8686
r!: 4 | 5 // error, from class
8787
}
88+
89+
// #35327
90+
class L {
91+
a: any;
92+
constructor(arg: any) {
93+
this.a = arg;
94+
}
95+
}
96+
class M extends L {
97+
declare a: number;
98+
constructor(arg: number) {
99+
super(arg);
100+
console.log(this.a); // should be OK, M.a is ambient
101+
}
102+
}
88103

tests/baselines/reference/derivedUninitializedPropertyDeclaration.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@ class K extends J {
6565
q!: 1 | 2 | 3 // ok, extends a property from an interface
6666
r!: 4 | 5 // error, from class
6767
}
68+
69+
// #35327
70+
class L {
71+
a: any;
72+
constructor(arg: any) {
73+
this.a = arg;
74+
}
75+
}
76+
class M extends L {
77+
declare a: number;
78+
constructor(arg: number) {
79+
super(arg);
80+
console.log(this.a); // should be OK, M.a is ambient
81+
}
82+
}
6883

6984

7085
//// [derivedUninitializedPropertyDeclaration.js]
@@ -178,3 +193,19 @@ var K = /** @class */ (function (_super) {
178193
}
179194
return K;
180195
}(J));
196+
// #35327
197+
var L = /** @class */ (function () {
198+
function L(arg) {
199+
this.a = arg;
200+
}
201+
return L;
202+
}());
203+
var M = /** @class */ (function (_super) {
204+
__extends(M, _super);
205+
function M(arg) {
206+
var _this = _super.call(this, arg) || this;
207+
console.log(_this.a); // should be OK, M.a is ambient
208+
return _this;
209+
}
210+
return M;
211+
}(L));

tests/baselines/reference/derivedUninitializedPropertyDeclaration.symbols

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,44 @@ class K extends J {
147147
>r : Symbol(K.r, Decl(derivedUninitializedPropertyDeclaration.ts, 63, 17))
148148
}
149149

150+
// #35327
151+
class L {
152+
>L : Symbol(L, Decl(derivedUninitializedPropertyDeclaration.ts, 65, 1))
153+
154+
a: any;
155+
>a : Symbol(L.a, Decl(derivedUninitializedPropertyDeclaration.ts, 68, 9))
156+
157+
constructor(arg: any) {
158+
>arg : Symbol(arg, Decl(derivedUninitializedPropertyDeclaration.ts, 70, 16))
159+
160+
this.a = arg;
161+
>this.a : Symbol(L.a, Decl(derivedUninitializedPropertyDeclaration.ts, 68, 9))
162+
>this : Symbol(L, Decl(derivedUninitializedPropertyDeclaration.ts, 65, 1))
163+
>a : Symbol(L.a, Decl(derivedUninitializedPropertyDeclaration.ts, 68, 9))
164+
>arg : Symbol(arg, Decl(derivedUninitializedPropertyDeclaration.ts, 70, 16))
165+
}
166+
}
167+
class M extends L {
168+
>M : Symbol(M, Decl(derivedUninitializedPropertyDeclaration.ts, 73, 1))
169+
>L : Symbol(L, Decl(derivedUninitializedPropertyDeclaration.ts, 65, 1))
170+
171+
declare a: number;
172+
>a : Symbol(M.a, Decl(derivedUninitializedPropertyDeclaration.ts, 74, 19))
173+
174+
constructor(arg: number) {
175+
>arg : Symbol(arg, Decl(derivedUninitializedPropertyDeclaration.ts, 76, 16))
176+
177+
super(arg);
178+
>super : Symbol(L, Decl(derivedUninitializedPropertyDeclaration.ts, 65, 1))
179+
>arg : Symbol(arg, Decl(derivedUninitializedPropertyDeclaration.ts, 76, 16))
180+
181+
console.log(this.a); // should be OK, M.a is ambient
182+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
183+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
184+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
185+
>this.a : Symbol(M.a, Decl(derivedUninitializedPropertyDeclaration.ts, 74, 19))
186+
>this : Symbol(M, Decl(derivedUninitializedPropertyDeclaration.ts, 73, 1))
187+
>a : Symbol(M.a, Decl(derivedUninitializedPropertyDeclaration.ts, 74, 19))
188+
}
189+
}
190+

tests/baselines/reference/derivedUninitializedPropertyDeclaration.types

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,47 @@ class K extends J {
150150
>r : 5 | 4
151151
}
152152

153+
// #35327
154+
class L {
155+
>L : L
156+
157+
a: any;
158+
>a : any
159+
160+
constructor(arg: any) {
161+
>arg : any
162+
163+
this.a = arg;
164+
>this.a = arg : any
165+
>this.a : any
166+
>this : this
167+
>a : any
168+
>arg : any
169+
}
170+
}
171+
class M extends L {
172+
>M : M
173+
>L : L
174+
175+
declare a: number;
176+
>a : number
177+
178+
constructor(arg: number) {
179+
>arg : number
180+
181+
super(arg);
182+
>super(arg) : void
183+
>super : typeof L
184+
>arg : number
185+
186+
console.log(this.a); // should be OK, M.a is ambient
187+
>console.log(this.a) : void
188+
>console.log : (message?: any, ...optionalParams: any[]) => void
189+
>console : Console
190+
>log : (message?: any, ...optionalParams: any[]) => void
191+
>this.a : number
192+
>this : this
193+
>a : number
194+
}
195+
}
196+

tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,18 @@ class K extends J {
6565
q!: 1 | 2 | 3 // ok, extends a property from an interface
6666
r!: 4 | 5 // error, from class
6767
}
68+
69+
// #35327
70+
class L {
71+
a: any;
72+
constructor(arg: any) {
73+
this.a = arg;
74+
}
75+
}
76+
class M extends L {
77+
declare a: number;
78+
constructor(arg: number) {
79+
super(arg);
80+
console.log(this.a); // should be OK, M.a is ambient
81+
}
82+
}

0 commit comments

Comments
 (0)