diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b58012e3188bf..f9cd044a79331 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12531,6 +12531,11 @@ namespace ts { return indexSymbol && getIndexDeclarationOfIndexSymbol(indexSymbol, kind); } + function getIndexDeclarationOfSymbolTable(symbolTable: SymbolTable | undefined, kind: IndexKind): IndexSignatureDeclaration | undefined { + const indexSymbol = symbolTable && getIndexSymbolFromSymbolTable(symbolTable); + return indexSymbol && getIndexDeclarationOfIndexSymbol(indexSymbol, kind); + } + function getIndexDeclarationOfIndexSymbol(indexSymbol: Symbol, kind: IndexKind): IndexSignatureDeclaration | undefined { const syntaxKind = kind === IndexKind.Number ? SyntaxKind.NumberKeyword : SyntaxKind.StringKeyword; if (indexSymbol?.declarations) { @@ -36773,15 +36778,16 @@ namespace ts { } } - function checkIndexConstraints(type: Type) { - const declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, IndexKind.Number); - const declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, IndexKind.String); + function checkIndexConstraints(type: Type, isStatic?: boolean) { + const declaredNumberIndexer = getIndexDeclarationOfSymbolTable(isStatic ? type.symbol?.exports : type.symbol?.members, IndexKind.Number); + const declaredStringIndexer = getIndexDeclarationOfSymbolTable(isStatic ? type.symbol?.exports : type.symbol?.members, IndexKind.String); const stringIndexType = getIndexTypeOfType(type, IndexKind.String); const numberIndexType = getIndexTypeOfType(type, IndexKind.Number); if (stringIndexType || numberIndexType) { forEach(getPropertiesOfObjectType(type), prop => { + if (isStatic && prop.flags & SymbolFlags.Prototype) return; const propType = getTypeOfSymbol(prop); checkIndexConstraintForProperty(prop, propType, type, declaredStringIndexer, stringIndexType, IndexKind.String); checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number); @@ -37160,7 +37166,7 @@ namespace ts { if (produceDiagnostics) { checkIndexConstraints(type); - checkIndexConstraints(staticType); + checkIndexConstraints(staticType, /*isStatic*/ true); checkTypeForDuplicateIndexSignatures(node); checkPropertyInitialization(node); } diff --git a/tests/baselines/reference/staticIndexSignature3.errors.txt b/tests/baselines/reference/staticIndexSignature3.errors.txt new file mode 100644 index 0000000000000..4b57e0ab00d70 --- /dev/null +++ b/tests/baselines/reference/staticIndexSignature3.errors.txt @@ -0,0 +1,33 @@ +tests/cases/conformance/classes/staticIndexSignature/staticIndexSignature3.ts(12,5): error TS2413: Numeric index type '1' is not assignable to string index type 'boolean'. + + +==== tests/cases/conformance/classes/staticIndexSignature/staticIndexSignature3.ts (1 errors) ==== + class B { + static readonly [s: string]: number; + static readonly [s: number]: 42 | 233 + } + + class D extends B { + static readonly [s: string]: number + } + + class ED extends D { + static readonly [s: string]: boolean + static readonly [s: number]: 1 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2413: Numeric index type '1' is not assignable to string index type 'boolean'. + } + + class DD extends D { + static readonly [s: string]: 421 + } + + const a = B["f"]; + const b = B[42]; + const c = D["f"] + const d = D[42] + const e = ED["f"] + const f = ED[42] + const g = DD["f"] + const h = DD[42] + \ No newline at end of file diff --git a/tests/baselines/reference/staticIndexSignatureAndNormalIndexSignature.js b/tests/baselines/reference/staticIndexSignatureAndNormalIndexSignature.js new file mode 100644 index 0000000000000..7772ce21e4f7a --- /dev/null +++ b/tests/baselines/reference/staticIndexSignatureAndNormalIndexSignature.js @@ -0,0 +1,12 @@ +//// [staticIndexSignatureAndNormalIndexSignature.ts] +class Foo { + [p: string]: any; + static [p: string]: number; +} + +//// [staticIndexSignatureAndNormalIndexSignature.js] +var Foo = /** @class */ (function () { + function Foo() { + } + return Foo; +}()); diff --git a/tests/baselines/reference/staticIndexSignatureAndNormalIndexSignature.symbols b/tests/baselines/reference/staticIndexSignatureAndNormalIndexSignature.symbols new file mode 100644 index 0000000000000..e37f4e334f2f5 --- /dev/null +++ b/tests/baselines/reference/staticIndexSignatureAndNormalIndexSignature.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/staticIndexSignatureAndNormalIndexSignature.ts === +class Foo { +>Foo : Symbol(Foo, Decl(staticIndexSignatureAndNormalIndexSignature.ts, 0, 0)) + + [p: string]: any; +>p : Symbol(p, Decl(staticIndexSignatureAndNormalIndexSignature.ts, 1, 5)) + + static [p: string]: number; +>p : Symbol(p, Decl(staticIndexSignatureAndNormalIndexSignature.ts, 2, 12)) +} diff --git a/tests/baselines/reference/staticIndexSignatureAndNormalIndexSignature.types b/tests/baselines/reference/staticIndexSignatureAndNormalIndexSignature.types new file mode 100644 index 0000000000000..811f7d2879a3d --- /dev/null +++ b/tests/baselines/reference/staticIndexSignatureAndNormalIndexSignature.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/staticIndexSignatureAndNormalIndexSignature.ts === +class Foo { +>Foo : Foo + + [p: string]: any; +>p : string + + static [p: string]: number; +>p : string +} diff --git a/tests/cases/compiler/staticIndexSignatureAndNormalIndexSignature.ts b/tests/cases/compiler/staticIndexSignatureAndNormalIndexSignature.ts new file mode 100644 index 0000000000000..20cfe3f4e120e --- /dev/null +++ b/tests/cases/compiler/staticIndexSignatureAndNormalIndexSignature.ts @@ -0,0 +1,4 @@ +class Foo { + [p: string]: any; + static [p: string]: number; +} \ No newline at end of file