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

Report error only on local declaration with additional related information #49746

Merged
merged 3 commits into from Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/compiler/checker.ts
Expand Up @@ -39377,8 +39377,9 @@ namespace ts {
}
const indexInfos = getApplicableIndexInfos(type, propNameType);
const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined;
const localPropDeclaration = declaration && declaration.kind === SyntaxKind.BinaryExpression ||
name && name.kind === SyntaxKind.ComputedPropertyName || getParentOfSymbol(prop) === type.symbol ? declaration : undefined;
const propDeclaration = declaration && declaration.kind === SyntaxKind.BinaryExpression ||
name && name.kind === SyntaxKind.ComputedPropertyName ? declaration : undefined;
const localPropDeclaration = getParentOfSymbol(prop) === type.symbol ? declaration : undefined;
for (const info of indexInfos) {
const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfNode(info.declaration)) === type.symbol ? info.declaration : undefined;
// We check only when (a) the property is declared in the containing type, or (b) the applicable index signature is declared
Expand All @@ -39387,8 +39388,12 @@ namespace ts {
const errorNode = localPropDeclaration || localIndexDeclaration ||
(interfaceDeclaration && !some(getBaseTypes(type as InterfaceType), base => !!getPropertyOfObjectType(base, prop.escapedName) && !!getIndexTypeOfType(base, info.keyType)) ? interfaceDeclaration : undefined);
if (errorNode && !isTypeAssignableTo(propType, info.type)) {
error(errorNode, Diagnostics.Property_0_of_type_1_is_not_assignable_to_2_index_type_3,
const diagnostic = createError(errorNode, Diagnostics.Property_0_of_type_1_is_not_assignable_to_2_index_type_3,
symbolToString(prop), typeToString(propType), typeToString(info.keyType), typeToString(info.type));
if (propDeclaration && errorNode !== propDeclaration) {
addRelatedInfo(diagnostic, createDiagnosticForNode(propDeclaration, Diagnostics._0_is_declared_here, symbolToString(prop)));
}
diagnostics.add(diagnostic);
}
}
}
Expand Down
@@ -1,4 +1,4 @@
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'.
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'.
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'.


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

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

class D extends C {
// No error when the indexer is in a class more derived than the computed property
[s: string]: Foo2;
~~~~~~~~~~~~~~~~~~
!!! error TS2411: Property '["get1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
!!! related TS2728 tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES5.ts:5:9: '["get1"]' is declared here.
set ["set1"](p: Foo) { }
~~~~~~~~
!!! error TS2411: Property '["set1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
Expand Down
@@ -1,4 +1,4 @@
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'.
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'.
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'.


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

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

class D extends C {
// No error when the indexer is in a class more derived than the computed property
[s: string]: Foo2;
~~~~~~~~~~~~~~~~~~
!!! error TS2411: Property '["get1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
!!! related TS2728 tests/cases/conformance/es6/computedProperties/computedPropertyNames45_ES6.ts:5:9: '["get1"]' is declared here.
set ["set1"](p: Foo) { }
~~~~~~~~
!!! error TS2411: Property '["set1"]' of type 'Foo' is not assignable to 'string' index type 'Foo2'.
Expand Down
49 changes: 49 additions & 0 deletions tests/baselines/reference/indexSignatureInOtherFile.errors.txt
@@ -0,0 +1,49 @@
tests/cases/compiler/index.ts(2,3): error TS2411: Property '[Symbol.iterator]' of type '() => IterableIterator<any>' is not assignable to 'symbol' index type 'string'.
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'.


==== tests/cases/compiler/index.ts (2 errors) ====
class Test extends Array1 {
[key: symbol]: string
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2411: Property '[Symbol.iterator]' of type '() => IterableIterator<any>' is not assignable to 'symbol' index type 'string'.
!!! related TS2728 tests/cases/compiler/other.ts:14:3: '[Symbol.iterator]' is declared here.
~~~~~~~~~~~~~~~~~~~~~
!!! 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'.
!!! related TS2728 tests/cases/compiler/other.ts:23:3: '[Symbol.unscopables]' is declared here.
}

==== tests/cases/compiler/other.ts (0 errors) ====
interface Array1<T> {
length: number;
[n: number]: T;
}

interface ArrayConstructor1 {
new(arrayLength?: number): Array1<any>;
}

declare var Array1: ArrayConstructor1;

// iterable.d.ts
interface Array1<T> {
[Symbol.iterator](): IterableIterator<T>;
}

// symbol.wellknown.d.ts
interface Array1<T> {
/**
* Returns an object whose properties have the value 'true'
* when they will be absent when used in a 'with' statement.
*/
[Symbol.unscopables](): {
copyWithin: boolean;
entries: boolean;
fill: boolean;
find: boolean;
findIndex: boolean;
keys: boolean;
values: boolean;
};
}

46 changes: 46 additions & 0 deletions tests/baselines/reference/indexSignatureInOtherFile.js
@@ -0,0 +1,46 @@
//// [tests/cases/compiler/indexSignatureInOtherFile.ts] ////

//// [index.ts]
class Test extends Array1 {
[key: symbol]: string
}

//// [other.ts]
interface Array1<T> {
length: number;
[n: number]: T;
}

interface ArrayConstructor1 {
new(arrayLength?: number): Array1<any>;
}

declare var Array1: ArrayConstructor1;

// iterable.d.ts
interface Array1<T> {
[Symbol.iterator](): IterableIterator<T>;
}

// symbol.wellknown.d.ts
interface Array1<T> {
/**
* Returns an object whose properties have the value 'true'
* when they will be absent when used in a 'with' statement.
*/
[Symbol.unscopables](): {
copyWithin: boolean;
entries: boolean;
fill: boolean;
find: boolean;
findIndex: boolean;
keys: boolean;
values: boolean;
};
}


//// [index.js]
class Test extends Array1 {
}
//// [other.js]
87 changes: 87 additions & 0 deletions tests/baselines/reference/indexSignatureInOtherFile.symbols
@@ -0,0 +1,87 @@
=== tests/cases/compiler/index.ts ===
class Test extends Array1 {
>Test : Symbol(Test, Decl(index.ts, 0, 0))
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))

[key: symbol]: string
>key : Symbol(key, Decl(index.ts, 1, 3))
}

=== tests/cases/compiler/other.ts ===
interface Array1<T> {
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))
>T : Symbol(T, Decl(other.ts, 0, 17), Decl(other.ts, 12, 17), Decl(other.ts, 17, 17))

length: number;
>length : Symbol(Array1.length, Decl(other.ts, 0, 21))

[n: number]: T;
>n : Symbol(n, Decl(other.ts, 2, 3))
>T : Symbol(T, Decl(other.ts, 0, 17), Decl(other.ts, 12, 17), Decl(other.ts, 17, 17))
}

interface ArrayConstructor1 {
>ArrayConstructor1 : Symbol(ArrayConstructor1, Decl(other.ts, 3, 1))

new(arrayLength?: number): Array1<any>;
>arrayLength : Symbol(arrayLength, Decl(other.ts, 6, 6))
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))
}

declare var Array1: ArrayConstructor1;
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))
>ArrayConstructor1 : Symbol(ArrayConstructor1, Decl(other.ts, 3, 1))

// iterable.d.ts
interface Array1<T> {
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))
>T : Symbol(T, Decl(other.ts, 0, 17), Decl(other.ts, 12, 17), Decl(other.ts, 17, 17))

[Symbol.iterator](): IterableIterator<T>;
>[Symbol.iterator] : Symbol(Array1[Symbol.iterator], Decl(other.ts, 12, 21))
>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
>IterableIterator : Symbol(IterableIterator, Decl(lib.es2015.iterable.d.ts, --, --))
>T : Symbol(T, Decl(other.ts, 0, 17), Decl(other.ts, 12, 17), Decl(other.ts, 17, 17))
}

// symbol.wellknown.d.ts
interface Array1<T> {
>Array1 : Symbol(Array1, Decl(other.ts, 0, 0), Decl(other.ts, 9, 11), Decl(other.ts, 9, 38), Decl(other.ts, 14, 1))
>T : Symbol(T, Decl(other.ts, 0, 17), Decl(other.ts, 12, 17), Decl(other.ts, 17, 17))

/**
* Returns an object whose properties have the value 'true'
* when they will be absent when used in a 'with' statement.
*/
[Symbol.unscopables](): {
>[Symbol.unscopables] : Symbol(Array1[Symbol.unscopables], Decl(other.ts, 17, 21))
>Symbol.unscopables : Symbol(SymbolConstructor.unscopables, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>unscopables : Symbol(SymbolConstructor.unscopables, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))

copyWithin: boolean;
>copyWithin : Symbol(copyWithin, Decl(other.ts, 22, 27))

entries: boolean;
>entries : Symbol(entries, Decl(other.ts, 23, 26))

fill: boolean;
>fill : Symbol(fill, Decl(other.ts, 24, 23))

find: boolean;
>find : Symbol(find, Decl(other.ts, 25, 20))

findIndex: boolean;
>findIndex : Symbol(findIndex, Decl(other.ts, 26, 20))

keys: boolean;
>keys : Symbol(keys, Decl(other.ts, 27, 25))

values: boolean;
>values : Symbol(values, Decl(other.ts, 28, 20))

};
}

71 changes: 71 additions & 0 deletions tests/baselines/reference/indexSignatureInOtherFile.types
@@ -0,0 +1,71 @@
=== tests/cases/compiler/index.ts ===
class Test extends Array1 {
>Test : Test
>Array1 : Array1<any>

[key: symbol]: string
>key : symbol
}

=== tests/cases/compiler/other.ts ===
interface Array1<T> {
length: number;
>length : number

[n: number]: T;
>n : number
}

interface ArrayConstructor1 {
new(arrayLength?: number): Array1<any>;
>arrayLength : number
}

declare var Array1: ArrayConstructor1;
>Array1 : ArrayConstructor1

// iterable.d.ts
interface Array1<T> {
[Symbol.iterator](): IterableIterator<T>;
>[Symbol.iterator] : () => IterableIterator<T>
>Symbol.iterator : unique symbol
>Symbol : SymbolConstructor
>iterator : unique symbol
}

// symbol.wellknown.d.ts
interface Array1<T> {
/**
* Returns an object whose properties have the value 'true'
* when they will be absent when used in a 'with' statement.
*/
[Symbol.unscopables](): {
>[Symbol.unscopables] : () => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean;}
>Symbol.unscopables : unique symbol
>Symbol : SymbolConstructor
>unscopables : unique symbol

copyWithin: boolean;
>copyWithin : boolean

entries: boolean;
>entries : boolean

fill: boolean;
>fill : boolean

find: boolean;
>find : boolean

findIndex: boolean;
>findIndex : boolean

keys: boolean;
>keys : boolean

values: boolean;
>values : boolean

};
}

48 changes: 48 additions & 0 deletions tests/baselines/reference/indexSignatureInOtherFile1.errors.txt
@@ -0,0 +1,48 @@
tests/cases/compiler/index.ts(2,3): error TS2411: Property '[Symbol.iterator]' of type '() => IterableIterator<any>' is not assignable to 'symbol' index type 'string'.
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'.


==== tests/cases/compiler/other.ts (0 errors) ====
interface Array1<T> {
length: number;
[n: number]: T;
}

interface ArrayConstructor1 {
new(arrayLength?: number): Array1<any>;
}

declare var Array1: ArrayConstructor1;

// iterable.d.ts
interface Array1<T> {
[Symbol.iterator](): IterableIterator<T>;
}

// symbol.wellknown.d.ts
interface Array1<T> {
/**
* Returns an object whose properties have the value 'true'
* when they will be absent when used in a 'with' statement.
*/
[Symbol.unscopables](): {
copyWithin: boolean;
entries: boolean;
fill: boolean;
find: boolean;
findIndex: boolean;
keys: boolean;
values: boolean;
};
}

==== tests/cases/compiler/index.ts (2 errors) ====
class Test extends Array1 {
[key: symbol]: string
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2411: Property '[Symbol.iterator]' of type '() => IterableIterator<any>' is not assignable to 'symbol' index type 'string'.
!!! related TS2728 tests/cases/compiler/other.ts:14:3: '[Symbol.iterator]' is declared here.
~~~~~~~~~~~~~~~~~~~~~
!!! 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'.
!!! related TS2728 tests/cases/compiler/other.ts:23:3: '[Symbol.unscopables]' is declared here.
}