Skip to content

Commit b86ab7d

Browse files
authored
Stop reassigning .valueDeclaration to avoid replacing earlier declarations with late ones (#60857)
1 parent 0fb5e3a commit b86ab7d

17 files changed

+486
-13
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13657,9 +13657,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1365713657
symbol.declarations.push(member);
1365813658
}
1365913659
if (symbolFlags & SymbolFlags.Value) {
13660-
if (!symbol.valueDeclaration || symbol.valueDeclaration.kind !== member.kind) {
13661-
symbol.valueDeclaration = member;
13662-
}
13660+
setValueDeclaration(symbol, member);
1366313661
}
1366413662
}
1366513663

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS1.ts] ////
2+
3+
//// [index.js]
4+
// https://github.com/microsoft/TypeScript/issues/60590
5+
6+
export const kBar = Symbol("bar");
7+
8+
export class foo0 {
9+
/**
10+
* @protected
11+
* @type {null | string}
12+
*/
13+
[kBar] = null;
14+
15+
get bar() {
16+
return this[kBar];
17+
}
18+
/**
19+
* @type {string}
20+
*/
21+
set bar(value) {
22+
this[kBar] = value;
23+
}
24+
}
25+
26+
27+
//// [index.js]
28+
// https://github.com/microsoft/TypeScript/issues/60590
29+
export const kBar = Symbol("bar");
30+
export class foo0 {
31+
/**
32+
* @protected
33+
* @type {null | string}
34+
*/
35+
[kBar] = null;
36+
get bar() {
37+
return this[kBar];
38+
}
39+
/**
40+
* @type {string}
41+
*/
42+
set bar(value) {
43+
this[kBar] = value;
44+
}
45+
}
46+
47+
48+
//// [index.d.ts]
49+
export const kBar: unique symbol;
50+
export class foo0 {
51+
/**
52+
* @type {string}
53+
*/
54+
set bar(value: string | null);
55+
get bar(): string | null;
56+
/**
57+
* @protected
58+
* @type {null | string}
59+
*/
60+
protected [kBar]: null | string;
61+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS1.ts] ////
2+
3+
=== index.js ===
4+
// https://github.com/microsoft/TypeScript/issues/60590
5+
6+
export const kBar = Symbol("bar");
7+
>kBar : Symbol(kBar, Decl(index.js, 2, 12))
8+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
9+
10+
export class foo0 {
11+
>foo0 : Symbol(foo0, Decl(index.js, 2, 34))
12+
13+
/**
14+
* @protected
15+
* @type {null | string}
16+
*/
17+
[kBar] = null;
18+
>[kBar] : Symbol(foo0[kBar], Decl(index.js, 4, 19))
19+
>kBar : Symbol(kBar, Decl(index.js, 2, 12))
20+
21+
get bar() {
22+
>bar : Symbol(foo0.bar, Decl(index.js, 9, 18), Decl(index.js, 13, 5))
23+
24+
return this[kBar];
25+
>this : Symbol(foo0, Decl(index.js, 2, 34))
26+
>kBar : Symbol(kBar, Decl(index.js, 2, 12))
27+
}
28+
/**
29+
* @type {string}
30+
*/
31+
set bar(value) {
32+
>bar : Symbol(foo0.bar, Decl(index.js, 9, 18), Decl(index.js, 13, 5))
33+
>value : Symbol(value, Decl(index.js, 17, 12))
34+
35+
this[kBar] = value;
36+
>this : Symbol(foo0, Decl(index.js, 2, 34))
37+
>kBar : Symbol(kBar, Decl(index.js, 2, 12))
38+
>value : Symbol(value, Decl(index.js, 17, 12))
39+
}
40+
}
41+
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS1.ts] ////
2+
3+
=== index.js ===
4+
// https://github.com/microsoft/TypeScript/issues/60590
5+
6+
export const kBar = Symbol("bar");
7+
>kBar : unique symbol
8+
> : ^^^^^^^^^^^^^
9+
>Symbol("bar") : unique symbol
10+
> : ^^^^^^^^^^^^^
11+
>Symbol : SymbolConstructor
12+
> : ^^^^^^^^^^^^^^^^^
13+
>"bar" : "bar"
14+
> : ^^^^^
15+
16+
export class foo0 {
17+
>foo0 : foo0
18+
> : ^^^^
19+
20+
/**
21+
* @protected
22+
* @type {null | string}
23+
*/
24+
[kBar] = null;
25+
>[kBar] : string | null
26+
> : ^^^^^^^^^^^^^
27+
>kBar : unique symbol
28+
> : ^^^^^^^^^^^^^
29+
30+
get bar() {
31+
>bar : string | null
32+
> : ^^^^^^^^^^^^^
33+
34+
return this[kBar];
35+
>this[kBar] : string | null
36+
> : ^^^^^^^^^^^^^
37+
>this : this
38+
> : ^^^^
39+
>kBar : unique symbol
40+
> : ^^^^^^^^^^^^^
41+
}
42+
/**
43+
* @type {string}
44+
*/
45+
set bar(value) {
46+
>bar : string | null
47+
> : ^^^^^^^^^^^^^
48+
>value : string | null
49+
> : ^^^^^^^^^^^^^
50+
51+
this[kBar] = value;
52+
>this[kBar] = value : string | null
53+
> : ^^^^^^^^^^^^^
54+
>this[kBar] : string | null
55+
> : ^^^^^^^^^^^^^
56+
>this : this
57+
> : ^^^^
58+
>kBar : unique symbol
59+
> : ^^^^^^^^^^^^^
60+
>value : string | null
61+
> : ^^^^^^^^^^^^^
62+
}
63+
}
64+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS2.ts] ////
2+
3+
//// [index.js]
4+
const prop = 'prop';
5+
6+
export class foo1 {
7+
constructor() {
8+
this[prop] = 'bar'
9+
}
10+
11+
/**
12+
* @protected
13+
* @type {string}
14+
*/
15+
[prop] = 'baz';
16+
}
17+
18+
19+
//// [index.js]
20+
const prop = 'prop';
21+
export class foo1 {
22+
constructor() {
23+
this[prop] = 'bar';
24+
}
25+
/**
26+
* @protected
27+
* @type {string}
28+
*/
29+
[prop] = 'baz';
30+
}
31+
32+
33+
//// [index.d.ts]
34+
export class foo1 {
35+
/**
36+
* @protected
37+
* @type {string}
38+
*/
39+
protected prop: string;
40+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS2.ts] ////
2+
3+
=== index.js ===
4+
const prop = 'prop';
5+
>prop : Symbol(prop, Decl(index.js, 0, 5))
6+
7+
export class foo1 {
8+
>foo1 : Symbol(foo1, Decl(index.js, 0, 20))
9+
10+
constructor() {
11+
this[prop] = 'bar'
12+
>this : Symbol(foo1, Decl(index.js, 0, 20))
13+
>prop : Symbol(prop, Decl(index.js, 0, 5))
14+
}
15+
16+
/**
17+
* @protected
18+
* @type {string}
19+
*/
20+
[prop] = 'baz';
21+
>[prop] : Symbol(foo1[prop], Decl(index.js, 5, 5))
22+
>prop : Symbol(prop, Decl(index.js, 0, 5))
23+
}
24+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS2.ts] ////
2+
3+
=== index.js ===
4+
const prop = 'prop';
5+
>prop : "prop"
6+
> : ^^^^^^
7+
>'prop' : "prop"
8+
> : ^^^^^^
9+
10+
export class foo1 {
11+
>foo1 : foo1
12+
> : ^^^^
13+
14+
constructor() {
15+
this[prop] = 'bar'
16+
>this[prop] = 'bar' : "bar"
17+
> : ^^^^^
18+
>this[prop] : string
19+
> : ^^^^^^
20+
>this : this
21+
> : ^^^^
22+
>prop : "prop"
23+
> : ^^^^^^
24+
>'bar' : "bar"
25+
> : ^^^^^
26+
}
27+
28+
/**
29+
* @protected
30+
* @type {string}
31+
*/
32+
[prop] = 'baz';
33+
>[prop] : string
34+
> : ^^^^^^
35+
>prop : "prop"
36+
> : ^^^^^^
37+
>'baz' : "baz"
38+
> : ^^^^^
39+
}
40+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
index.js(5,9): error TS2322: Type 'number' is not assignable to type 'string'.
2+
3+
4+
==== index.js (1 errors) ====
5+
const prop = 'prop';
6+
7+
export class foo2 {
8+
constructor() {
9+
this[prop] = 12;
10+
~~~~~~~~~~
11+
!!! error TS2322: Type 'number' is not assignable to type 'string'.
12+
}
13+
14+
/**
15+
* @protected
16+
* @type {string}
17+
*/
18+
prop = 'baz';
19+
}
20+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS3.ts] ////
2+
3+
//// [index.js]
4+
const prop = 'prop';
5+
6+
export class foo2 {
7+
constructor() {
8+
this[prop] = 12;
9+
}
10+
11+
/**
12+
* @protected
13+
* @type {string}
14+
*/
15+
prop = 'baz';
16+
}
17+
18+
19+
//// [index.js]
20+
const prop = 'prop';
21+
export class foo2 {
22+
constructor() {
23+
this[prop] = 12;
24+
}
25+
/**
26+
* @protected
27+
* @type {string}
28+
*/
29+
prop = 'baz';
30+
}
31+
32+
33+
//// [index.d.ts]
34+
export class foo2 {
35+
/**
36+
* @protected
37+
* @type {string}
38+
*/
39+
protected prop: string;
40+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS3.ts] ////
2+
3+
=== index.js ===
4+
const prop = 'prop';
5+
>prop : Symbol(prop, Decl(index.js, 0, 5))
6+
7+
export class foo2 {
8+
>foo2 : Symbol(foo2, Decl(index.js, 0, 20))
9+
10+
constructor() {
11+
this[prop] = 12;
12+
>this : Symbol(foo2, Decl(index.js, 0, 20))
13+
>prop : Symbol(prop, Decl(index.js, 0, 5))
14+
}
15+
16+
/**
17+
* @protected
18+
* @type {string}
19+
*/
20+
prop = 'baz';
21+
>prop : Symbol(foo2.prop, Decl(index.js, 5, 5), Decl(index.js, 3, 19))
22+
}
23+

0 commit comments

Comments
 (0)