Skip to content

Commit 5b0eea4

Browse files
authored
Report error only on local declaration with additional related information (#49746)
* Add test where the errors are reported in different file Test for #49739 * Report error only on local declaration with additional related information Fixes #49739 * Handle existing tests
1 parent c0461be commit 5b0eea4

14 files changed

+600
-12
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39552,8 +39552,9 @@ namespace ts {
3955239552
}
3955339553
const indexInfos = getApplicableIndexInfos(type, propNameType);
3955439554
const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined;
39555-
const localPropDeclaration = declaration && declaration.kind === SyntaxKind.BinaryExpression ||
39556-
name && name.kind === SyntaxKind.ComputedPropertyName || getParentOfSymbol(prop) === type.symbol ? declaration : undefined;
39555+
const propDeclaration = declaration && declaration.kind === SyntaxKind.BinaryExpression ||
39556+
name && name.kind === SyntaxKind.ComputedPropertyName ? declaration : undefined;
39557+
const localPropDeclaration = getParentOfSymbol(prop) === type.symbol ? declaration : undefined;
3955739558
for (const info of indexInfos) {
3955839559
const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfNode(info.declaration)) === type.symbol ? info.declaration : undefined;
3955939560
// We check only when (a) the property is declared in the containing type, or (b) the applicable index signature is declared
@@ -39562,8 +39563,12 @@ namespace ts {
3956239563
const errorNode = localPropDeclaration || localIndexDeclaration ||
3956339564
(interfaceDeclaration && !some(getBaseTypes(type as InterfaceType), base => !!getPropertyOfObjectType(base, prop.escapedName) && !!getIndexTypeOfType(base, info.keyType)) ? interfaceDeclaration : undefined);
3956439565
if (errorNode && !isTypeAssignableTo(propType, info.type)) {
39565-
error(errorNode, Diagnostics.Property_0_of_type_1_is_not_assignable_to_2_index_type_3,
39566+
const diagnostic = createError(errorNode, Diagnostics.Property_0_of_type_1_is_not_assignable_to_2_index_type_3,
3956639567
symbolToString(prop), typeToString(propType), typeToString(info.keyType), typeToString(info.type));
39568+
if (propDeclaration && errorNode !== propDeclaration) {
39569+
addRelatedInfo(diagnostic, createDiagnosticForNode(propDeclaration, Diagnostics._0_is_declared_here, symbolToString(prop)));
39570+
}
39571+
diagnostics.add(diagnostic);
3956739572
}
3956839573
}
3956939574
}

tests/baselines/reference/computedPropertyNames45_ES5.errors.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES5.ts(5,9): error TS2411: Property '["get1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
1+
tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES5.ts(10,5): error TS2411: Property '["get1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
22
tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES5.ts(11,9): error TS2411: Property '["set1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
33

44

@@ -8,13 +8,14 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES5.ts(11
88

99
class C {
1010
get ["get1"]() { return new Foo }
11-
~~~~~~~~
12-
!!! error TS2411: Property '["get1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
1311
}
1412

1513
class D extends C {
1614
// No error when the indexer is in a class more derived than the computed property
1715
[s: string]: Foo2;
16+
~~~~~~~~~~~~~~~~~~
17+
!!! error TS2411: Property '["get1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
18+
!!! related TS2728 tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES5.ts:5:9: '["get1"]' is declared here.
1819
set ["set1"](p: Foo) { }
1920
~~~~~~~~
2021
!!! error TS2411: Property '["set1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.

tests/baselines/reference/computedPropertyNames45_ES6.errors.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES6.ts(5,9): error TS2411: Property '["get1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
1+
tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES6.ts(10,5): error TS2411: Property '["get1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
22
tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES6.ts(11,9): error TS2411: Property '["set1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
33

44

@@ -8,13 +8,14 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES6.ts(11
88

99
class C {
1010
get ["get1"]() { return new Foo }
11-
~~~~~~~~
12-
!!! error TS2411: Property '["get1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
1311
}
1412

1513
class D extends C {
1614
// No error when the indexer is in a class more derived than the computed property
1715
[s: string]: Foo2;
16+
~~~~~~~~~~~~~~~~~~
17+
!!! error TS2411: Property '["get1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
18+
!!! related TS2728 tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES6.ts:5:9: '["get1"]' is declared here.
1819
set ["set1"](p: Foo) { }
1920
~~~~~~~~
2021
!!! error TS2411: Property '["set1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
tests/cases/compiler/index.ts(2,3): error TS2411: Property '[Symbol.iterator]' of type '() => IterableIterator<any>' is not assignable to 'symbol' index type 'string'.
2+
tests/cases/compiler/index.ts(2,3): error TS2411: Property '[Symbol.unscopables]' of type '() => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }' is not assignable to 'symbol' index type 'string'.
3+
4+
5+
==== tests/cases/compiler/index.ts (2 errors) ====
6+
class Test extends Array1 {
7+
[key: symbol]: string
8+
~~~~~~~~~~~~~~~~~~~~~
9+
!!! error TS2411: Property '[Symbol.iterator]' of type '() => IterableIterator<any>' is not assignable to 'symbol' index type 'string'.
10+
!!! related TS2728 tests/cases/compiler/other.ts:14:3: '[Symbol.iterator]' is declared here.
11+
~~~~~~~~~~~~~~~~~~~~~
12+
!!! error TS2411: Property '[Symbol.unscopables]' of type '() => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }' is not assignable to 'symbol' index type 'string'.
13+
!!! related TS2728 tests/cases/compiler/other.ts:23:3: '[Symbol.unscopables]' is declared here.
14+
}
15+
16+
==== tests/cases/compiler/other.ts (0 errors) ====
17+
interface Array1<T> {
18+
length: number;
19+
[n: number]: T;
20+
}
21+
22+
interface ArrayConstructor1 {
23+
new(arrayLength?: number): Array1<any>;
24+
}
25+
26+
declare var Array1: ArrayConstructor1;
27+
28+
// iterable.d.ts
29+
interface Array1<T> {
30+
[Symbol.iterator](): IterableIterator<T>;
31+
}
32+
33+
// symbol.wellknown.d.ts
34+
interface Array1<T> {
35+
/**
36+
* Returns an object whose properties have the value 'true'
37+
* when they will be absent when used in a 'with' statement.
38+
*/
39+
[Symbol.unscopables](): {
40+
copyWithin: boolean;
41+
entries: boolean;
42+
fill: boolean;
43+
find: boolean;
44+
findIndex: boolean;
45+
keys: boolean;
46+
values: boolean;
47+
};
48+
}
49+
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//// [tests/cases/compiler/indexSignatureInOtherFile.ts] ////
2+
3+
//// [index.ts]
4+
class Test extends Array1 {
5+
[key: symbol]: string
6+
}
7+
8+
//// [other.ts]
9+
interface Array1<T> {
10+
length: number;
11+
[n: number]: T;
12+
}
13+
14+
interface ArrayConstructor1 {
15+
new(arrayLength?: number): Array1<any>;
16+
}
17+
18+
declare var Array1: ArrayConstructor1;
19+
20+
// iterable.d.ts
21+
interface Array1<T> {
22+
[Symbol.iterator](): IterableIterator<T>;
23+
}
24+
25+
// symbol.wellknown.d.ts
26+
interface Array1<T> {
27+
/**
28+
* Returns an object whose properties have the value 'true'
29+
* when they will be absent when used in a 'with' statement.
30+
*/
31+
[Symbol.unscopables](): {
32+
copyWithin: boolean;
33+
entries: boolean;
34+
fill: boolean;
35+
find: boolean;
36+
findIndex: boolean;
37+
keys: boolean;
38+
values: boolean;
39+
};
40+
}
41+
42+
43+
//// [index.js]
44+
class Test extends Array1 {
45+
}
46+
//// [other.js]
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
=== tests/cases/compiler/index.ts ===
2+
class Test extends Array1 {
3+
>Test : Symbol(Test, Decl(index.ts, 0, 0))
4+
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))
5+
6+
[key: symbol]: string
7+
>key : Symbol(key, Decl(index.ts, 1, 3))
8+
}
9+
10+
=== tests/cases/compiler/other.ts ===
11+
interface Array1<T> {
12+
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))
13+
>T : Symbol(T, Decl(other.ts, 0, 17), Decl(other.ts, 12, 17), Decl(other.ts, 17, 17))
14+
15+
length: number;
16+
>length : Symbol(Array1.length, Decl(other.ts, 0, 21))
17+
18+
[n: number]: T;
19+
>n : Symbol(n, Decl(other.ts, 2, 3))
20+
>T : Symbol(T, Decl(other.ts, 0, 17), Decl(other.ts, 12, 17), Decl(other.ts, 17, 17))
21+
}
22+
23+
interface ArrayConstructor1 {
24+
>ArrayConstructor1 : Symbol(ArrayConstructor1, Decl(other.ts, 3, 1))
25+
26+
new(arrayLength?: number): Array1<any>;
27+
>arrayLength : Symbol(arrayLength, Decl(other.ts, 6, 6))
28+
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))
29+
}
30+
31+
declare var Array1: ArrayConstructor1;
32+
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))
33+
>ArrayConstructor1 : Symbol(ArrayConstructor1, Decl(other.ts, 3, 1))
34+
35+
// iterable.d.ts
36+
interface Array1<T> {
37+
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))
38+
>T : Symbol(T, Decl(other.ts, 0, 17), Decl(other.ts, 12, 17), Decl(other.ts, 17, 17))
39+
40+
[Symbol.iterator](): IterableIterator<T>;
41+
>[Symbol.iterator] : Symbol(Array1[Symbol.iterator], Decl(other.ts, 12, 21))
42+
>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
43+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
44+
>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
45+
>IterableIterator : Symbol(IterableIterator, Decl(lib.es2015.iterable.d.ts, --, --))
46+
>T : Symbol(T, Decl(other.ts, 0, 17), Decl(other.ts, 12, 17), Decl(other.ts, 17, 17))
47+
}
48+
49+
// symbol.wellknown.d.ts
50+
interface Array1<T> {
51+
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))
52+
>T : Symbol(T, Decl(other.ts, 0, 17), Decl(other.ts, 12, 17), Decl(other.ts, 17, 17))
53+
54+
/**
55+
* Returns an object whose properties have the value 'true'
56+
* when they will be absent when used in a 'with' statement.
57+
*/
58+
[Symbol.unscopables](): {
59+
>[Symbol.unscopables] : Symbol(Array1[Symbol.unscopables], Decl(other.ts, 17, 21))
60+
>Symbol.unscopables : Symbol(SymbolConstructor.unscopables, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
61+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
62+
>unscopables : Symbol(SymbolConstructor.unscopables, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
63+
64+
copyWithin: boolean;
65+
>copyWithin : Symbol(copyWithin, Decl(other.ts, 22, 27))
66+
67+
entries: boolean;
68+
>entries : Symbol(entries, Decl(other.ts, 23, 26))
69+
70+
fill: boolean;
71+
>fill : Symbol(fill, Decl(other.ts, 24, 23))
72+
73+
find: boolean;
74+
>find : Symbol(find, Decl(other.ts, 25, 20))
75+
76+
findIndex: boolean;
77+
>findIndex : Symbol(findIndex, Decl(other.ts, 26, 20))
78+
79+
keys: boolean;
80+
>keys : Symbol(keys, Decl(other.ts, 27, 25))
81+
82+
values: boolean;
83+
>values : Symbol(values, Decl(other.ts, 28, 20))
84+
85+
};
86+
}
87+
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
=== tests/cases/compiler/index.ts ===
2+
class Test extends Array1 {
3+
>Test : Test
4+
>Array1 : Array1<any>
5+
6+
[key: symbol]: string
7+
>key : symbol
8+
}
9+
10+
=== tests/cases/compiler/other.ts ===
11+
interface Array1<T> {
12+
length: number;
13+
>length : number
14+
15+
[n: number]: T;
16+
>n : number
17+
}
18+
19+
interface ArrayConstructor1 {
20+
new(arrayLength?: number): Array1<any>;
21+
>arrayLength : number
22+
}
23+
24+
declare var Array1: ArrayConstructor1;
25+
>Array1 : ArrayConstructor1
26+
27+
// iterable.d.ts
28+
interface Array1<T> {
29+
[Symbol.iterator](): IterableIterator<T>;
30+
>[Symbol.iterator] : () => IterableIterator<T>
31+
>Symbol.iterator : unique symbol
32+
>Symbol : SymbolConstructor
33+
>iterator : unique symbol
34+
}
35+
36+
// symbol.wellknown.d.ts
37+
interface Array1<T> {
38+
/**
39+
* Returns an object whose properties have the value 'true'
40+
* when they will be absent when used in a 'with' statement.
41+
*/
42+
[Symbol.unscopables](): {
43+
>[Symbol.unscopables] : () => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean;}
44+
>Symbol.unscopables : unique symbol
45+
>Symbol : SymbolConstructor
46+
>unscopables : unique symbol
47+
48+
copyWithin: boolean;
49+
>copyWithin : boolean
50+
51+
entries: boolean;
52+
>entries : boolean
53+
54+
fill: boolean;
55+
>fill : boolean
56+
57+
find: boolean;
58+
>find : boolean
59+
60+
findIndex: boolean;
61+
>findIndex : boolean
62+
63+
keys: boolean;
64+
>keys : boolean
65+
66+
values: boolean;
67+
>values : boolean
68+
69+
};
70+
}
71+
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
tests/cases/compiler/index.ts(2,3): error TS2411: Property '[Symbol.iterator]' of type '() => IterableIterator<any>' is not assignable to 'symbol' index type 'string'.
2+
tests/cases/compiler/index.ts(2,3): error TS2411: Property '[Symbol.unscopables]' of type '() => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }' is not assignable to 'symbol' index type 'string'.
3+
4+
5+
==== tests/cases/compiler/other.ts (0 errors) ====
6+
interface Array1<T> {
7+
length: number;
8+
[n: number]: T;
9+
}
10+
11+
interface ArrayConstructor1 {
12+
new(arrayLength?: number): Array1<any>;
13+
}
14+
15+
declare var Array1: ArrayConstructor1;
16+
17+
// iterable.d.ts
18+
interface Array1<T> {
19+
[Symbol.iterator](): IterableIterator<T>;
20+
}
21+
22+
// symbol.wellknown.d.ts
23+
interface Array1<T> {
24+
/**
25+
* Returns an object whose properties have the value 'true'
26+
* when they will be absent when used in a 'with' statement.
27+
*/
28+
[Symbol.unscopables](): {
29+
copyWithin: boolean;
30+
entries: boolean;
31+
fill: boolean;
32+
find: boolean;
33+
findIndex: boolean;
34+
keys: boolean;
35+
values: boolean;
36+
};
37+
}
38+
39+
==== tests/cases/compiler/index.ts (2 errors) ====
40+
class Test extends Array1 {
41+
[key: symbol]: string
42+
~~~~~~~~~~~~~~~~~~~~~
43+
!!! error TS2411: Property '[Symbol.iterator]' of type '() => IterableIterator<any>' is not assignable to 'symbol' index type 'string'.
44+
!!! related TS2728 tests/cases/compiler/other.ts:14:3: '[Symbol.iterator]' is declared here.
45+
~~~~~~~~~~~~~~~~~~~~~
46+
!!! error TS2411: Property '[Symbol.unscopables]' of type '() => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }' is not assignable to 'symbol' index type 'string'.
47+
!!! related TS2728 tests/cases/compiler/other.ts:23:3: '[Symbol.unscopables]' is declared here.
48+
}

0 commit comments

Comments
 (0)