Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop reassigning .valueDeclaration to avoid replacing earlier declarations with late ones #60857

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13197,10 +13197,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
else if (!member.symbol.isReplaceableByMethod) {
symbol.declarations.push(member);
}
if (symbolFlags & SymbolFlags.Value) {
if (!symbol.valueDeclaration || symbol.valueDeclaration.kind !== member.kind) {
symbol.valueDeclaration = member;
}
if (symbolFlags & SymbolFlags.Value && !symbol.valueDeclaration) {
symbol.valueDeclaration = member;
}
}

Expand Down
61 changes: 61 additions & 0 deletions tests/baselines/reference/lateBoundAssignmentCandidateJS1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS1.ts] ////

//// [index.js]
// https://github.com/microsoft/TypeScript/issues/60590

export const kBar = Symbol("bar");

export class foo0 {
/**
* @protected
* @type {null | string}
*/
[kBar] = null;

get bar() {
return this[kBar];
}
/**
* @type {string}
*/
set bar(value) {
this[kBar] = value;
}
}


//// [index.js]
// https://github.com/microsoft/TypeScript/issues/60590
export const kBar = Symbol("bar");
export class foo0 {
/**
* @protected
* @type {null | string}
*/
[kBar] = null;
get bar() {
return this[kBar];
}
/**
* @type {string}
*/
set bar(value) {
this[kBar] = value;
}
}


//// [index.d.ts]
export const kBar: unique symbol;
export class foo0 {
/**
* @type {string}
*/
set bar(value: string | null);
get bar(): string | null;
/**
* @protected
* @type {null | string}
*/
protected [kBar]: null | string;
}
41 changes: 41 additions & 0 deletions tests/baselines/reference/lateBoundAssignmentCandidateJS1.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS1.ts] ////

=== index.js ===
// https://github.com/microsoft/TypeScript/issues/60590

export const kBar = Symbol("bar");
>kBar : Symbol(kBar, Decl(index.js, 2, 12))
>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, --, --))

export class foo0 {
>foo0 : Symbol(foo0, Decl(index.js, 2, 34))

/**
* @protected
* @type {null | string}
*/
[kBar] = null;
>[kBar] : Symbol(foo0[kBar], Decl(index.js, 4, 19))
>kBar : Symbol(kBar, Decl(index.js, 2, 12))

get bar() {
>bar : Symbol(foo0.bar, Decl(index.js, 9, 18), Decl(index.js, 13, 5))

return this[kBar];
>this : Symbol(foo0, Decl(index.js, 2, 34))
>kBar : Symbol(kBar, Decl(index.js, 2, 12))
}
/**
* @type {string}
*/
set bar(value) {
>bar : Symbol(foo0.bar, Decl(index.js, 9, 18), Decl(index.js, 13, 5))
>value : Symbol(value, Decl(index.js, 17, 12))

this[kBar] = value;
>this : Symbol(foo0, Decl(index.js, 2, 34))
>kBar : Symbol(kBar, Decl(index.js, 2, 12))
>value : Symbol(value, Decl(index.js, 17, 12))
}
}

64 changes: 64 additions & 0 deletions tests/baselines/reference/lateBoundAssignmentCandidateJS1.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS1.ts] ////

=== index.js ===
// https://github.com/microsoft/TypeScript/issues/60590

export const kBar = Symbol("bar");
>kBar : unique symbol
> : ^^^^^^^^^^^^^
>Symbol("bar") : unique symbol
> : ^^^^^^^^^^^^^
>Symbol : SymbolConstructor
> : ^^^^^^^^^^^^^^^^^
>"bar" : "bar"
> : ^^^^^

export class foo0 {
>foo0 : foo0
> : ^^^^

/**
* @protected
* @type {null | string}
*/
[kBar] = null;
>[kBar] : string | null
> : ^^^^^^^^^^^^^
>kBar : unique symbol
> : ^^^^^^^^^^^^^

get bar() {
>bar : string | null
> : ^^^^^^^^^^^^^

return this[kBar];
>this[kBar] : string | null
> : ^^^^^^^^^^^^^
>this : this
> : ^^^^
>kBar : unique symbol
> : ^^^^^^^^^^^^^
}
/**
* @type {string}
*/
set bar(value) {
>bar : string | null
> : ^^^^^^^^^^^^^
>value : string | null
> : ^^^^^^^^^^^^^

this[kBar] = value;
>this[kBar] = value : string | null
> : ^^^^^^^^^^^^^
>this[kBar] : string | null
> : ^^^^^^^^^^^^^
>this : this
> : ^^^^
>kBar : unique symbol
> : ^^^^^^^^^^^^^
>value : string | null
> : ^^^^^^^^^^^^^
}
}

40 changes: 40 additions & 0 deletions tests/baselines/reference/lateBoundAssignmentCandidateJS2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS2.ts] ////

//// [index.js]
const prop = 'prop';

export class foo1 {
constructor() {
this[prop] = 'bar'
}

/**
* @protected
* @type {string}
*/
[prop] = 'baz';
}


//// [index.js]
const prop = 'prop';
export class foo1 {
constructor() {
this[prop] = 'bar';
}
/**
* @protected
* @type {string}
*/
[prop] = 'baz';
}


//// [index.d.ts]
export class foo1 {
/**
* @protected
* @type {string}
*/
protected prop: string;
}
24 changes: 24 additions & 0 deletions tests/baselines/reference/lateBoundAssignmentCandidateJS2.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS2.ts] ////

=== index.js ===
const prop = 'prop';
>prop : Symbol(prop, Decl(index.js, 0, 5))

export class foo1 {
>foo1 : Symbol(foo1, Decl(index.js, 0, 20))

constructor() {
this[prop] = 'bar'
>this : Symbol(foo1, Decl(index.js, 0, 20))
>prop : Symbol(prop, Decl(index.js, 0, 5))
}

/**
* @protected
* @type {string}
*/
[prop] = 'baz';
>[prop] : Symbol(foo1[prop], Decl(index.js, 5, 5))
>prop : Symbol(prop, Decl(index.js, 0, 5))
}

40 changes: 40 additions & 0 deletions tests/baselines/reference/lateBoundAssignmentCandidateJS2.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS2.ts] ////

=== index.js ===
const prop = 'prop';
>prop : "prop"
> : ^^^^^^
>'prop' : "prop"
> : ^^^^^^

export class foo1 {
>foo1 : foo1
> : ^^^^

constructor() {
this[prop] = 'bar'
>this[prop] = 'bar' : "bar"
> : ^^^^^
>this[prop] : string
> : ^^^^^^
>this : this
> : ^^^^
>prop : "prop"
> : ^^^^^^
>'bar' : "bar"
> : ^^^^^
}

/**
* @protected
* @type {string}
*/
[prop] = 'baz';
>[prop] : string
> : ^^^^^^
>prop : "prop"
> : ^^^^^^
>'baz' : "baz"
> : ^^^^^
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
index.js(5,9): error TS2322: Type 'number' is not assignable to type 'string'.


==== index.js (1 errors) ====
const prop = 'prop';

export class foo2 {
constructor() {
this[prop] = 12;
~~~~~~~~~~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
}

/**
* @protected
* @type {string}
*/
prop = 'baz';
}

40 changes: 40 additions & 0 deletions tests/baselines/reference/lateBoundAssignmentCandidateJS3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS3.ts] ////

//// [index.js]
const prop = 'prop';

export class foo2 {
constructor() {
this[prop] = 12;
}

/**
* @protected
* @type {string}
*/
prop = 'baz';
}


//// [index.js]
const prop = 'prop';
export class foo2 {
constructor() {
this[prop] = 12;
}
/**
* @protected
* @type {string}
*/
prop = 'baz';
}


//// [index.d.ts]
export class foo2 {
/**
* @protected
* @type {string}
*/
protected prop: string;
}
23 changes: 23 additions & 0 deletions tests/baselines/reference/lateBoundAssignmentCandidateJS3.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//// [tests/cases/compiler/lateBoundAssignmentCandidateJS3.ts] ////

=== index.js ===
const prop = 'prop';
>prop : Symbol(prop, Decl(index.js, 0, 5))

export class foo2 {
>foo2 : Symbol(foo2, Decl(index.js, 0, 20))

constructor() {
this[prop] = 12;
>this : Symbol(foo2, Decl(index.js, 0, 20))
>prop : Symbol(prop, Decl(index.js, 0, 5))
}

/**
* @protected
* @type {string}
*/
prop = 'baz';
>prop : Symbol(foo2.prop, Decl(index.js, 5, 5), Decl(index.js, 3, 19))
}

Loading
Loading