diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 99c6da8f9b..61661fbf5b 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -4271,7 +4271,7 @@ func (c *Checker) checkClassLikeDeclaration(node *ast.Node) { } c.checkIndexConstraints(classType, symbol, false /*isStaticIndex*/) c.checkIndexConstraints(staticType, symbol, true /*isStaticIndex*/) - c.checkTypeForDuplicateIndexSignatures(node) + c.checkClassOrInterfaceForDuplicateIndexSignatures(node) c.checkPropertyInitialization(node) } @@ -4758,14 +4758,15 @@ func (c *Checker) checkIndexConstraintForIndexSignature(t *Type, checkInfo *Inde } } -func (c *Checker) checkTypeForDuplicateIndexSignatures(node *ast.Node) { - if ast.IsInterfaceDeclaration(node) { - // in case of merging interface declaration it is possible that we'll enter this check procedure several times for every declaration - // to prevent this run check only for the first declaration of a given kind - if symbol := c.getSymbolOfDeclaration(node); len(symbol.Declarations) != 0 && symbol.Declarations[0] != node { - return - } +func (c *Checker) checkClassOrInterfaceForDuplicateIndexSignatures(node *ast.Node) { + // Only check the type once + if links := c.declaredTypeLinks.Get(c.getSymbolOfDeclaration(node)); !links.indexSignaturesChecked { + links.indexSignaturesChecked = true + c.checkTypeForDuplicateIndexSignatures(node) } +} + +func (c *Checker) checkTypeForDuplicateIndexSignatures(node *ast.Node) { // TypeScript 1.0 spec (April 2014) // 3.7.4: An object type can contain at most one string index signature and one numeric index signature. // 8.5: A class declaration can have at most one string index member declaration and one numeric index member declaration @@ -4865,8 +4866,8 @@ func (c *Checker) checkInterfaceDeclaration(node *ast.Node) { symbol := c.getSymbolOfDeclaration(node) c.checkTypeParameterListsIdentical(symbol) // Only check this symbol once - firstInterfaceDecl := ast.GetDeclarationOfKind(symbol, ast.KindInterfaceDeclaration) - if node == firstInterfaceDecl { + if links := c.declaredTypeLinks.Get(symbol); !links.interfaceChecked { + links.interfaceChecked = true t := c.getDeclaredTypeOfSymbol(symbol) typeWithThis := c.getTypeWithThisArgument(t, nil, false) // run subsequent checks only if first set succeeded @@ -4886,7 +4887,7 @@ func (c *Checker) checkInterfaceDeclaration(node *ast.Node) { c.checkTypeReferenceNode(heritageElement) } c.checkSourceElements(node.Members()) - c.checkTypeForDuplicateIndexSignatures(node) + c.checkClassOrInterfaceForDuplicateIndexSignatures(node) c.registerForUnusedIdentifiersCheck(node) } diff --git a/internal/checker/types.go b/internal/checker/types.go index c06599452d..e7f57e076d 100644 --- a/internal/checker/types.go +++ b/internal/checker/types.go @@ -193,8 +193,10 @@ type TypeAliasLinks struct { // Links for declared types (type parameters, class types, interface types, enums) type DeclaredTypeLinks struct { - declaredType *Type - typeParametersChecked bool + declaredType *Type + interfaceChecked bool + indexSignaturesChecked bool + typeParametersChecked bool } // Links for switch clauses diff --git a/testdata/baselines/reference/submodule/conformance/1.0lib-noErrors.errors.txt b/testdata/baselines/reference/submodule/conformance/1.0lib-noErrors.errors.txt index 98677a0ed7..7aab34df4b 100644 --- a/testdata/baselines/reference/submodule/conformance/1.0lib-noErrors.errors.txt +++ b/testdata/baselines/reference/submodule/conformance/1.0lib-noErrors.errors.txt @@ -1,7 +1,10 @@ +1.0lib-noErrors.ts(92,5): error TS2374: Duplicate index signature for type 'string'. 1.0lib-noErrors.ts(130,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Object' must be of type 'ObjectConstructor', but here has type '{ (): any; (value: any): any; new (value?: any): Object; prototype: Object; getPrototypeOf(o: any): any; getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor; getOwnPropertyNames(o: any): string[]; create(o: any, properties?: PropertyDescriptorMap): any; defineProperty(o: any, p: string, attributes: PropertyDescriptor): any; defineProperties(o: any, properties: PropertyDescriptorMap): any; seal(o: any): any; freeze(o: any): any; preventExtensions(o: any): any; isSealed(o: any): boolean; isFrozen(o: any): boolean; isExtensible(o: any): boolean; keys(o: any): string[]; }'. 1.0lib-noErrors.ts(251,5): error TS2687: All declarations of 'length' must have identical modifiers. 1.0lib-noErrors.ts(258,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Function' must be of type 'FunctionConstructor', but here has type '{ (...args: string[]): Function; new (...args: string[]): Function; prototype: Function; }'. +1.0lib-noErrors.ts(269,5): error TS2374: Duplicate index signature for type 'number'. 1.0lib-noErrors.ts(414,5): error TS2687: All declarations of 'length' must have identical modifiers. +1.0lib-noErrors.ts(424,5): error TS2374: Duplicate index signature for type 'number'. 1.0lib-noErrors.ts(430,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'String' must be of type 'StringConstructor', but here has type '{ (value?: any): string; new (value?: any): String; prototype: String; fromCharCode(...codes: number[]): string; }'. 1.0lib-noErrors.ts(439,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Boolean' must be of type 'BooleanConstructor', but here has type '{ (value?: any): boolean; new (value?: any): Boolean; prototype: Boolean; }'. 1.0lib-noErrors.ts(472,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Number' must be of type 'NumberConstructor', but here has type '{ (value?: any): number; new (value?: any): Number; prototype: Number; MAX_VALUE: number; MIN_VALUE: number; NaN: number; NEGATIVE_INFINITY: number; POSITIVE_INFINITY: number; }'. @@ -14,6 +17,11 @@ 1.0lib-noErrors.ts(516,5): error TS2687: All declarations of 'SQRT1_2' must have identical modifiers. 1.0lib-noErrors.ts(518,5): error TS2687: All declarations of 'SQRT2' must have identical modifiers. 1.0lib-noErrors.ts(767,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Date' must be of type 'DateConstructor', but here has type '{ (): string; new (): Date; new (value: number): Date; new (value: string): Date; new (year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date; prototype: Date; parse(s: string): number; UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number; now(): number; }'. +1.0lib-noErrors.ts(793,11): error TS2430: Interface 'RegExpExecArray' incorrectly extends interface 'string[]'. + Types of property 'concat' are incompatible. + Type '(...items: string[][]) => string[]' is not assignable to type '{ (...items: ConcatArray[]): string[]; (...items: (string | ConcatArray)[]): string[]; (...items: U[]): string[]; (...items: string[]): string[]; }'. + Types of parameters 'items' and 'items' are incompatible. + Type 'string' is not assignable to type 'string[]'. 1.0lib-noErrors.ts(840,5): error TS2687: All declarations of 'source' must have identical modifiers. 1.0lib-noErrors.ts(843,5): error TS2687: All declarations of 'global' must have identical modifiers. 1.0lib-noErrors.ts(846,5): error TS2687: All declarations of 'ignoreCase' must have identical modifiers. @@ -26,10 +34,11 @@ 1.0lib-noErrors.ts(909,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'SyntaxError' must be of type 'SyntaxErrorConstructor', but here has type '{ (message?: string): SyntaxError; new (message?: string): SyntaxError; prototype: SyntaxError; }'. 1.0lib-noErrors.ts(917,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'TypeError' must be of type 'TypeErrorConstructor', but here has type '{ (message?: string): TypeError; new (message?: string): TypeError; prototype: TypeError; }'. 1.0lib-noErrors.ts(925,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'URIError' must be of type 'URIErrorConstructor', but here has type '{ (message?: string): URIError; new (message?: string): URIError; prototype: URIError; }'. +1.0lib-noErrors.ts(1132,5): error TS2374: Duplicate index signature for type 'number'. 1.0lib-noErrors.ts(1134,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Array' must be of type 'ArrayConstructor', but here has type '{ (arrayLength?: number): any[]; (arrayLength: number): T[]; (...items: T[]): T[]; new (arrayLength?: number): any[]; new (arrayLength: number): T[]; new (...items: T[]): T[]; isArray(arg: any): boolean; prototype: any[]; }'. -==== 1.0lib-noErrors.ts (29 errors) ==== +==== 1.0lib-noErrors.ts (34 errors) ==== /* ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use @@ -122,6 +131,8 @@ interface PropertyDescriptorMap { [s: string]: PropertyDescriptor; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2374: Duplicate index signature for type 'string'. } interface Object { @@ -307,6 +318,8 @@ interface IArguments { [index: number]: any; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2374: Duplicate index signature for type 'number'. length: number; callee: Function; } @@ -464,6 +477,8 @@ substr(from: number, length?: number): string; [index: number]: string; + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2374: Duplicate index signature for type 'number'. } /** @@ -861,6 +876,12 @@ } interface RegExpExecArray { + ~~~~~~~~~~~~~~~ +!!! error TS2430: Interface 'RegExpExecArray' incorrectly extends interface 'string[]'. +!!! error TS2430: Types of property 'concat' are incompatible. +!!! error TS2430: Type '(...items: string[][]) => string[]' is not assignable to type '{ (...items: ConcatArray[]): string[]; (...items: (string | ConcatArray)[]): string[]; (...items: U[]): string[]; (...items: string[]): string[]; }'. +!!! error TS2430: Types of parameters 'items' and 'items' are incompatible. +!!! error TS2430: Type 'string' is not assignable to type 'string[]'. [index: number]: string; length: number; @@ -1232,6 +1253,8 @@ length: number; [n: number]: T; + ~~~~~~~~~~~~~~~ +!!! error TS2374: Duplicate index signature for type 'number'. } declare var Array: { ~~~~~ diff --git a/testdata/baselines/reference/submodule/conformance/1.0lib-noErrors.errors.txt.diff b/testdata/baselines/reference/submodule/conformance/1.0lib-noErrors.errors.txt.diff index 7749e18f6c..43b4e215d5 100644 --- a/testdata/baselines/reference/submodule/conformance/1.0lib-noErrors.errors.txt.diff +++ b/testdata/baselines/reference/submodule/conformance/1.0lib-noErrors.errors.txt.diff @@ -2,10 +2,13 @@ +++ new.1.0lib-noErrors.errors.txt @@= skipped -0, +0 lines =@@ - ++1.0lib-noErrors.ts(92,5): error TS2374: Duplicate index signature for type 'string'. +1.0lib-noErrors.ts(130,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Object' must be of type 'ObjectConstructor', but here has type '{ (): any; (value: any): any; new (value?: any): Object; prototype: Object; getPrototypeOf(o: any): any; getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor; getOwnPropertyNames(o: any): string[]; create(o: any, properties?: PropertyDescriptorMap): any; defineProperty(o: any, p: string, attributes: PropertyDescriptor): any; defineProperties(o: any, properties: PropertyDescriptorMap): any; seal(o: any): any; freeze(o: any): any; preventExtensions(o: any): any; isSealed(o: any): boolean; isFrozen(o: any): boolean; isExtensible(o: any): boolean; keys(o: any): string[]; }'. +1.0lib-noErrors.ts(251,5): error TS2687: All declarations of 'length' must have identical modifiers. +1.0lib-noErrors.ts(258,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Function' must be of type 'FunctionConstructor', but here has type '{ (...args: string[]): Function; new (...args: string[]): Function; prototype: Function; }'. ++1.0lib-noErrors.ts(269,5): error TS2374: Duplicate index signature for type 'number'. +1.0lib-noErrors.ts(414,5): error TS2687: All declarations of 'length' must have identical modifiers. ++1.0lib-noErrors.ts(424,5): error TS2374: Duplicate index signature for type 'number'. +1.0lib-noErrors.ts(430,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'String' must be of type 'StringConstructor', but here has type '{ (value?: any): string; new (value?: any): String; prototype: String; fromCharCode(...codes: number[]): string; }'. +1.0lib-noErrors.ts(439,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Boolean' must be of type 'BooleanConstructor', but here has type '{ (value?: any): boolean; new (value?: any): Boolean; prototype: Boolean; }'. +1.0lib-noErrors.ts(472,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Number' must be of type 'NumberConstructor', but here has type '{ (value?: any): number; new (value?: any): Number; prototype: Number; MAX_VALUE: number; MIN_VALUE: number; NaN: number; NEGATIVE_INFINITY: number; POSITIVE_INFINITY: number; }'. @@ -18,6 +21,11 @@ +1.0lib-noErrors.ts(516,5): error TS2687: All declarations of 'SQRT1_2' must have identical modifiers. +1.0lib-noErrors.ts(518,5): error TS2687: All declarations of 'SQRT2' must have identical modifiers. +1.0lib-noErrors.ts(767,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Date' must be of type 'DateConstructor', but here has type '{ (): string; new (): Date; new (value: number): Date; new (value: string): Date; new (year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date; prototype: Date; parse(s: string): number; UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number; now(): number; }'. ++1.0lib-noErrors.ts(793,11): error TS2430: Interface 'RegExpExecArray' incorrectly extends interface 'string[]'. ++ Types of property 'concat' are incompatible. ++ Type '(...items: string[][]) => string[]' is not assignable to type '{ (...items: ConcatArray[]): string[]; (...items: (string | ConcatArray)[]): string[]; (...items: U[]): string[]; (...items: string[]): string[]; }'. ++ Types of parameters 'items' and 'items' are incompatible. ++ Type 'string' is not assignable to type 'string[]'. +1.0lib-noErrors.ts(840,5): error TS2687: All declarations of 'source' must have identical modifiers. +1.0lib-noErrors.ts(843,5): error TS2687: All declarations of 'global' must have identical modifiers. +1.0lib-noErrors.ts(846,5): error TS2687: All declarations of 'ignoreCase' must have identical modifiers. @@ -30,10 +38,11 @@ +1.0lib-noErrors.ts(909,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'SyntaxError' must be of type 'SyntaxErrorConstructor', but here has type '{ (message?: string): SyntaxError; new (message?: string): SyntaxError; prototype: SyntaxError; }'. +1.0lib-noErrors.ts(917,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'TypeError' must be of type 'TypeErrorConstructor', but here has type '{ (message?: string): TypeError; new (message?: string): TypeError; prototype: TypeError; }'. +1.0lib-noErrors.ts(925,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'URIError' must be of type 'URIErrorConstructor', but here has type '{ (message?: string): URIError; new (message?: string): URIError; prototype: URIError; }'. ++1.0lib-noErrors.ts(1132,5): error TS2374: Duplicate index signature for type 'number'. +1.0lib-noErrors.ts(1134,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'Array' must be of type 'ArrayConstructor', but here has type '{ (arrayLength?: number): any[]; (arrayLength: number): T[]; (...items: T[]): T[]; new (arrayLength?: number): any[]; new (arrayLength: number): T[]; new (...items: T[]): T[]; isArray(arg: any): boolean; prototype: any[]; }'. + + -+==== 1.0lib-noErrors.ts (29 errors) ==== ++==== 1.0lib-noErrors.ts (34 errors) ==== + /* ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use @@ -126,6 +135,8 @@ + + interface PropertyDescriptorMap { + [s: string]: PropertyDescriptor; ++ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++!!! error TS2374: Duplicate index signature for type 'string'. + } + + interface Object { @@ -311,6 +322,8 @@ + + interface IArguments { + [index: number]: any; ++ ~~~~~~~~~~~~~~~~~~~~~ ++!!! error TS2374: Duplicate index signature for type 'number'. + length: number; + callee: Function; + } @@ -468,6 +481,8 @@ + substr(from: number, length?: number): string; + + [index: number]: string; ++ ~~~~~~~~~~~~~~~~~~~~~~~~ ++!!! error TS2374: Duplicate index signature for type 'number'. + } + + /** @@ -865,6 +880,12 @@ + } + + interface RegExpExecArray { ++ ~~~~~~~~~~~~~~~ ++!!! error TS2430: Interface 'RegExpExecArray' incorrectly extends interface 'string[]'. ++!!! error TS2430: Types of property 'concat' are incompatible. ++!!! error TS2430: Type '(...items: string[][]) => string[]' is not assignable to type '{ (...items: ConcatArray[]): string[]; (...items: (string | ConcatArray)[]): string[]; (...items: U[]): string[]; (...items: string[]): string[]; }'. ++!!! error TS2430: Types of parameters 'items' and 'items' are incompatible. ++!!! error TS2430: Type 'string' is not assignable to type 'string[]'. + [index: number]: string; + length: number; + @@ -1236,6 +1257,8 @@ + length: number; + + [n: number]: T; ++ ~~~~~~~~~~~~~~~ ++!!! error TS2374: Duplicate index signature for type 'number'. + } + declare var Array: { + ~~~~~