From 5c56b03fb90be61f517140f053ad6c0c5943bf60 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 4 Sep 2024 12:02:52 -0700 Subject: [PATCH 1/8] First draft of late bound index signature behavior --- src/compiler/checker.ts | 117 ++++++++++++++---- ...ssNonUniqueSymbolMethodHasSymbolIndexer.js | 38 ++++++ ...UniqueSymbolMethodHasSymbolIndexer.symbols | 42 +++++++ ...onUniqueSymbolMethodHasSymbolIndexer.types | 63 ++++++++++ ...ssNonUniqueSymbolMethodHasSymbolIndexer.ts | 15 +++ 5 files changed, 252 insertions(+), 23 deletions(-) create mode 100644 tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.js create mode 100644 tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.symbols create mode 100644 tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.types create mode 100644 tests/cases/compiler/classNonUniqueSymbolMethodHasSymbolIndexer.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 52e6862110f53..c6d9bd69acd70 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1121,6 +1121,7 @@ import { WideningContext, WithStatement, YieldExpression, + isIndexSignatureDeclaration, } from "./_namespaces/ts.js"; import * as moduleSpecifiers from "./_namespaces/ts.moduleSpecifiers.js"; import * as performance from "./_namespaces/ts.performance.js"; @@ -13344,12 +13345,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * - The type of its expression is a string or numeric literal type, or is a `unique symbol` type. */ function isLateBindableName(node: DeclarationName): node is LateBoundName { + return isLateBindableAST(node) + && isTypeUsableAsPropertyName(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached((node as ElementAccessExpression).argumentExpression)); + } + + function isLateBindableIndexSignature(node: DeclarationName): node is LateBoundName { + return isLateBindableAST(node) + && isTypeUsableAsIndexSignature(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached((node as ElementAccessExpression).argumentExpression)); + } + + function isLateBindableAST(node: DeclarationName) { if (!isComputedPropertyName(node) && !isElementAccessExpression(node)) { return false; } const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression; - return isEntityNameExpression(expr) - && isTypeUsableAsPropertyName(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached(expr)); + return isEntityNameExpression(expr); + } + + function isTypeUsableAsIndexSignature(type: Type): boolean { + return isTypeAssignableTo(type, stringNumberSymbolType); } function isLateBoundName(name: __String): boolean { @@ -13366,6 +13380,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !!name && isLateBindableName(name); } + function hasLateBindableIndexSignature(node: Declaration) { + const name = getNameOfDeclaration(node); + return !!name && isLateBindableIndexSignature(name); + } + /** * Indicates whether a declaration has an early-bound name or a dynamic name that can be late-bound. */ @@ -13473,6 +13492,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.resolvedSymbol; } + function lateBindIndexSignature(parent: Symbol, earlySymbols: SymbolTable | undefined, lateSymbols: Map<__String, TransientSymbol>, decl: LateBoundDeclaration | LateBoundBinaryExpressionDeclaration) { + // First, late bind the index symbol itself, if needed + let indexSymbol = lateSymbols.get(InternalSymbolName.Index); + if (!indexSymbol) { + const early = earlySymbols?.get(InternalSymbolName.Index); + if (!early) { + indexSymbol = createSymbol(SymbolFlags.None, InternalSymbolName.Index, CheckFlags.Late); + } + else { + indexSymbol = cloneSymbol(early); + indexSymbol.links.checkFlags |= CheckFlags.Late; + } + lateSymbols.set(InternalSymbolName.Index, indexSymbol); + } + // Then just add the computed name as a late bound declaration + // (note: unlike `addDeclarationToLateBoundSymbol` we do not set up a `.lateSymbol` on `decl`'s links, + // since that would point at an index symbol and not a single property symbol, like most consumers would expect) + if (!indexSymbol.declarations) { + indexSymbol.declarations = [decl]; + } + else if (!decl.symbol.isReplaceableByMethod) { + indexSymbol.declarations.push(decl); + } + } + function getResolvedMembersOrExportsOfSymbol(symbol: Symbol, resolutionKind: MembersOrExportsResolutionKind): Map<__String, Symbol> { const links = getSymbolLinks(symbol); if (!links[resolutionKind]) { @@ -13496,6 +13540,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (hasLateBindableName(member)) { lateBindMember(symbol, earlySymbols, lateSymbols, member); } + else if (hasLateBindableIndexSignature(member)) { + lateBindIndexSignature(symbol, earlySymbols, lateSymbols, member as Node as LateBoundDeclaration | LateBoundBinaryExpressionDeclaration); + } } } } @@ -16191,7 +16238,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getIndexSymbol(symbol: Symbol): Symbol | undefined { - return symbol.members ? getIndexSymbolFromSymbolTable(symbol.members) : undefined; + return symbol.members ? getIndexSymbolFromSymbolTable(getMembersOfSymbol(symbol)) : undefined; } function getIndexSymbolFromSymbolTable(symbolTable: SymbolTable): Symbol | undefined { @@ -16210,17 +16257,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getIndexInfosOfIndexSymbol(indexSymbol: Symbol): IndexInfo[] { if (indexSymbol.declarations) { const indexInfos: IndexInfo[] = []; - for (const declaration of (indexSymbol.declarations as IndexSignatureDeclaration[])) { - if (declaration.parameters.length === 1) { - const parameter = declaration.parameters[0]; - if (parameter.type) { - forEachType(getTypeFromTypeNode(parameter.type), keyType => { - if (isValidIndexKeyType(keyType) && !findIndexInfo(indexInfos, keyType)) { - indexInfos.push(createIndexInfo(keyType, declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, hasEffectiveModifier(declaration, ModifierFlags.Readonly), declaration)); - } - }); + for (const declaration of indexSymbol.declarations) { + if (isIndexSignatureDeclaration(declaration)) { + if (declaration.parameters.length === 1) { + const parameter = declaration.parameters[0]; + if (parameter.type) { + forEachType(getTypeFromTypeNode(parameter.type), keyType => { + if (isValidIndexKeyType(keyType) && !findIndexInfo(indexInfos, keyType)) { + indexInfos.push(createIndexInfo(keyType, declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, hasEffectiveModifier(declaration, ModifierFlags.Readonly), declaration)); + } + }); + } } } + else if (hasLateBindableIndexSignature(declaration)) { + // TODO: Combine index signatures inferred for each member? Or make an index info for each? + // Combined? + // Pros: Easily made, definite compatability with all relevant signatures. + // Cons: Unspecific. Can't make the signature until all declarations are processed + // Individual? + // Pros: Can inject one at a time. Accurate read types via index info applicability filtering. + // Cons: Can't tell at-a-glance which signatures apply? Potentially lots of signatures to track? + // Individual probably better, so is what we do here. + + const declName = isBinaryExpression(declaration) ? declaration.left as ElementAccessExpression : (declaration as LateBoundDeclaration).name; + const keyType = isElementAccessExpression(declName) ? checkExpressionCached(declName.argumentExpression) : checkComputedPropertyName(declName); + forEachType(keyType, keyType => { + // First-in-wins on multiple declarations right now - combine? leave as multiple, but with compatability error? + if (isValidIndexKeyType(keyType) && !findIndexInfo(indexInfos, keyType)) { + indexInfos.push(createIndexInfo(keyType, getTypeOfVariableOrParameterOrProperty(declaration.symbol), hasEffectiveModifier(declaration, ModifierFlags.Readonly))); + } + }); + } } return indexInfos; } @@ -41566,18 +41634,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const indexSymbol = getIndexSymbol(getSymbolOfDeclaration(node)); if (indexSymbol?.declarations) { const indexSignatureMap = new Map(); - for (const declaration of (indexSymbol.declarations as IndexSignatureDeclaration[])) { - if (declaration.parameters.length === 1 && declaration.parameters[0].type) { - forEachType(getTypeFromTypeNode(declaration.parameters[0].type), type => { - const entry = indexSignatureMap.get(getTypeId(type)); - if (entry) { - entry.declarations.push(declaration); - } - else { - indexSignatureMap.set(getTypeId(type), { type, declarations: [declaration] }); - } - }); + for (const declaration of indexSymbol.declarations) { + if (isIndexSignatureDeclaration(declaration)) { + if (declaration.parameters.length === 1 && declaration.parameters[0].type) { + forEachType(getTypeFromTypeNode(declaration.parameters[0].type), type => { + const entry = indexSignatureMap.get(getTypeId(type)); + if (entry) { + entry.declarations.push(declaration); + } + else { + indexSignatureMap.set(getTypeId(type), { type, declarations: [declaration] }); + } + }); + } } + // Do nothing for late-bound index signatures: allow these to duplicate one another and explicit indexes } indexSignatureMap.forEach(entry => { if (entry.declarations.length > 1) { diff --git a/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.js b/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.js new file mode 100644 index 0000000000000..e52b25c702203 --- /dev/null +++ b/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.js @@ -0,0 +1,38 @@ +//// [tests/cases/compiler/classNonUniqueSymbolMethodHasSymbolIndexer.ts] //// + +//// [classNonUniqueSymbolMethodHasSymbolIndexer.ts] +declare const a: symbol; +export class A { + [a]() { return 1 }; +} +declare const e1: A[typeof a]; // no error, `A` has `symbol` index + +type Constructor = new (...args: any[]) => {}; +declare function Mix(classish: T): T & (new (...args: any[]) => {mixed: true}); + +export const Mixer = Mix(class { + [a]() { return 1 }; +}); + + +//// [classNonUniqueSymbolMethodHasSymbolIndexer.js] +export class A { + [a]() { return 1; } + ; +} +export const Mixer = Mix(class { + [a]() { return 1; } + ; +}); + + +//// [classNonUniqueSymbolMethodHasSymbolIndexer.d.ts] +export declare class A { +} +export declare const Mixer: { + new (): { + [x: symbol]: () => number; + }; +} & (new (...args: any[]) => { + mixed: true; +}); diff --git a/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.symbols b/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.symbols new file mode 100644 index 0000000000000..0c15a807cb4df --- /dev/null +++ b/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.symbols @@ -0,0 +1,42 @@ +//// [tests/cases/compiler/classNonUniqueSymbolMethodHasSymbolIndexer.ts] //// + +=== classNonUniqueSymbolMethodHasSymbolIndexer.ts === +declare const a: symbol; +>a : Symbol(a, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 0, 13)) + +export class A { +>A : Symbol(A, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 0, 24)) + + [a]() { return 1 }; +>[a] : Symbol(A[a], Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 1, 16)) +>a : Symbol(a, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 0, 13)) +} +declare const e1: A[typeof a]; // no error, `A` has `symbol` index +>e1 : Symbol(e1, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 4, 13)) +>A : Symbol(A, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 0, 24)) +>a : Symbol(a, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 0, 13)) + +type Constructor = new (...args: any[]) => {}; +>Constructor : Symbol(Constructor, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 4, 30)) +>args : Symbol(args, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 6, 24)) + +declare function Mix(classish: T): T & (new (...args: any[]) => {mixed: true}); +>Mix : Symbol(Mix, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 6, 46)) +>T : Symbol(T, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 7, 21)) +>Constructor : Symbol(Constructor, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 4, 30)) +>classish : Symbol(classish, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 7, 44)) +>T : Symbol(T, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 7, 21)) +>T : Symbol(T, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 7, 21)) +>args : Symbol(args, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 7, 68)) +>mixed : Symbol(mixed, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 7, 88)) + +export const Mixer = Mix(class { +>Mixer : Symbol(Mixer, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 9, 12)) +>Mix : Symbol(Mix, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 6, 46)) + + [a]() { return 1 }; +>[a] : Symbol((Anonymous class)[a], Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 9, 32)) +>a : Symbol(a, Decl(classNonUniqueSymbolMethodHasSymbolIndexer.ts, 0, 13)) + +}); + diff --git a/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.types b/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.types new file mode 100644 index 0000000000000..96d2b1023ce4d --- /dev/null +++ b/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.types @@ -0,0 +1,63 @@ +//// [tests/cases/compiler/classNonUniqueSymbolMethodHasSymbolIndexer.ts] //// + +=== classNonUniqueSymbolMethodHasSymbolIndexer.ts === +declare const a: symbol; +>a : symbol +> : ^^^^^^ + +export class A { +>A : A +> : ^ + + [a]() { return 1 }; +>[a] : () => number +> : ^^^^^^^^^^^^ +>a : symbol +> : ^^^^^^ +>1 : 1 +> : ^ +} +declare const e1: A[typeof a]; // no error, `A` has `symbol` index +>e1 : () => number +> : ^^^^^^^^^^^^ +>a : symbol +> : ^^^^^^ + +type Constructor = new (...args: any[]) => {}; +>Constructor : Constructor +> : ^^^^^^^^^^^ +>args : any[] +> : ^^^^^ + +declare function Mix(classish: T): T & (new (...args: any[]) => {mixed: true}); +>Mix : (classish: T) => T & (new (...args: any[]) => { mixed: true; }) +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>classish : T +> : ^ +>args : any[] +> : ^^^^^ +>mixed : true +> : ^^^^ +>true : true +> : ^^^^ + +export const Mixer = Mix(class { +>Mixer : typeof (Anonymous class) & (new (...args: any[]) => { mixed: true; }) +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^ +>Mix(class { [a]() { return 1 };}) : typeof (Anonymous class) & (new (...args: any[]) => { mixed: true; }) +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^ +>Mix : (classish: T) => T & (new (...args: any[]) => { mixed: true; }) +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>class { [a]() { return 1 };} : typeof (Anonymous class) +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + [a]() { return 1 }; +>[a] : () => number +> : ^^^^^^^^^^^^ +>a : symbol +> : ^^^^^^ +>1 : 1 +> : ^ + +}); + diff --git a/tests/cases/compiler/classNonUniqueSymbolMethodHasSymbolIndexer.ts b/tests/cases/compiler/classNonUniqueSymbolMethodHasSymbolIndexer.ts new file mode 100644 index 0000000000000..ad6f24ee91a7a --- /dev/null +++ b/tests/cases/compiler/classNonUniqueSymbolMethodHasSymbolIndexer.ts @@ -0,0 +1,15 @@ +// @target: es6 +// @strict: true +// @declaration: true +declare const a: symbol; +export class A { + [a]() { return 1 }; +} +declare const e1: A[typeof a]; // no error, `A` has `symbol` index + +type Constructor = new (...args: any[]) => {}; +declare function Mix(classish: T): T & (new (...args: any[]) => {mixed: true}); + +export const Mixer = Mix(class { + [a]() { return 1 }; +}); From 3342ff7105086ead2a370cb899cc503c6553c499 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 4 Sep 2024 15:26:45 -0700 Subject: [PATCH 2/8] Accept improved baselines --- .../reference/ES5SymbolProperty4.types | 3 ++- .../reference/ES5SymbolProperty5.errors.txt | 13 ++++++++++++ .../reference/ES5SymbolProperty5.types | 6 ++++-- ...pturedParametersInInitializers2.errors.txt | 5 ++++- .../computedPropertyNames12_ES5.errors.txt | 8 +++++++- .../computedPropertyNames12_ES6.errors.txt | 8 +++++++- .../computedPropertyNames2_ES5.errors.txt | 5 ++++- .../computedPropertyNames2_ES6.errors.txt | 5 ++++- ...PropertyNamesWithStaticProperty.errors.txt | 8 +++++++- ...solatedDeclarationErrorsClasses.errors.txt | 20 ++++++++++++++++++- .../reference/superSymbolIndexedAccess1.types | 10 ++++++---- 11 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 tests/baselines/reference/ES5SymbolProperty5.errors.txt diff --git a/tests/baselines/reference/ES5SymbolProperty4.types b/tests/baselines/reference/ES5SymbolProperty4.types index 7b02ee9fa6eb0..f05889a1aa625 100644 --- a/tests/baselines/reference/ES5SymbolProperty4.types +++ b/tests/baselines/reference/ES5SymbolProperty4.types @@ -23,7 +23,8 @@ class C { } (new C)[Symbol.iterator] ->(new C)[Symbol.iterator] : error +>(new C)[Symbol.iterator] : () => void +> : ^^^^^^^^^^ >(new C) : C > : ^ >new C : C diff --git a/tests/baselines/reference/ES5SymbolProperty5.errors.txt b/tests/baselines/reference/ES5SymbolProperty5.errors.txt new file mode 100644 index 0000000000000..b16cf1a9e4507 --- /dev/null +++ b/tests/baselines/reference/ES5SymbolProperty5.errors.txt @@ -0,0 +1,13 @@ +ES5SymbolProperty5.ts(7,26): error TS2554: Expected 0 arguments, but got 1. + + +==== ES5SymbolProperty5.ts (1 errors) ==== + var Symbol: { iterator: symbol }; + + class C { + [Symbol.iterator]() { } + } + + (new C)[Symbol.iterator](0) // Should error + ~ +!!! error TS2554: Expected 0 arguments, but got 1. \ No newline at end of file diff --git a/tests/baselines/reference/ES5SymbolProperty5.types b/tests/baselines/reference/ES5SymbolProperty5.types index 1fba891c701c5..99ba0bd4f6e21 100644 --- a/tests/baselines/reference/ES5SymbolProperty5.types +++ b/tests/baselines/reference/ES5SymbolProperty5.types @@ -23,8 +23,10 @@ class C { } (new C)[Symbol.iterator](0) // Should error ->(new C)[Symbol.iterator](0) : error ->(new C)[Symbol.iterator] : error +>(new C)[Symbol.iterator](0) : void +> : ^^^^ +>(new C)[Symbol.iterator] : () => void +> : ^^^^^^^^^^ >(new C) : C > : ^ >new C : C diff --git a/tests/baselines/reference/capturedParametersInInitializers2.errors.txt b/tests/baselines/reference/capturedParametersInInitializers2.errors.txt index 7f7e502bfbba2..c190ffe48f335 100644 --- a/tests/baselines/reference/capturedParametersInInitializers2.errors.txt +++ b/tests/baselines/reference/capturedParametersInInitializers2.errors.txt @@ -1,11 +1,12 @@ capturedParametersInInitializers2.ts(3,20): error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. capturedParametersInInitializers2.ts(4,14): error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. +capturedParametersInInitializers2.ts(6,9): error TS2411: Property '[z]' of type '() => number' is not assignable to 'number' index type 'number'. capturedParametersInInitializers2.ts(6,10): error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. capturedParametersInInitializers2.ts(13,26): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. capturedParametersInInitializers2.ts(13,27): error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. -==== capturedParametersInInitializers2.ts (5 errors) ==== +==== capturedParametersInInitializers2.ts (6 errors) ==== function foo( y = class { static c = x; @@ -16,6 +17,8 @@ capturedParametersInInitializers2.ts(13,27): error TS2373: Parameter 'y' cannot !!! error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. constructor() { x; } [z]() { return z; } + ~~~ +!!! error TS2411: Property '[z]' of type '() => number' is not assignable to 'number' index type 'number'. ~ !!! error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. }, diff --git a/tests/baselines/reference/computedPropertyNames12_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames12_ES5.errors.txt index 1544788d8281d..54170d241bb85 100644 --- a/tests/baselines/reference/computedPropertyNames12_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNames12_ES5.errors.txt @@ -3,12 +3,14 @@ computedPropertyNames12_ES5.ts(6,5): error TS1166: A computed property name in a computedPropertyNames12_ES5.ts(7,12): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. computedPropertyNames12_ES5.ts(8,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. computedPropertyNames12_ES5.ts(9,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. +computedPropertyNames12_ES5.ts(9,5): error TS2411: Property '[+s]' of type 'string' is not assignable to 'number' index type 'number'. +computedPropertyNames12_ES5.ts(9,5): error TS2411: Property '[+s]' of type 'string' is not assignable to 'string' index type 'number'. computedPropertyNames12_ES5.ts(12,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. computedPropertyNames12_ES5.ts(13,12): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. computedPropertyNames12_ES5.ts(15,12): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. -==== computedPropertyNames12_ES5.ts (8 errors) ==== +==== computedPropertyNames12_ES5.ts (10 errors) ==== var s: string; var n: number; var a: any; @@ -28,6 +30,10 @@ computedPropertyNames12_ES5.ts(15,12): error TS1166: A computed property name in [+s]: typeof s; ~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. + ~~~~ +!!! error TS2411: Property '[+s]' of type 'string' is not assignable to 'number' index type 'number'. + ~~~~ +!!! error TS2411: Property '[+s]' of type 'string' is not assignable to 'string' index type 'number'. static [""]: number; [0]: number; [a]: number; diff --git a/tests/baselines/reference/computedPropertyNames12_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames12_ES6.errors.txt index e6566f930510e..045be616de457 100644 --- a/tests/baselines/reference/computedPropertyNames12_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNames12_ES6.errors.txt @@ -3,12 +3,14 @@ computedPropertyNames12_ES6.ts(6,5): error TS1166: A computed property name in a computedPropertyNames12_ES6.ts(7,12): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. computedPropertyNames12_ES6.ts(8,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. computedPropertyNames12_ES6.ts(9,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. +computedPropertyNames12_ES6.ts(9,5): error TS2411: Property '[+s]' of type 'string' is not assignable to 'number' index type 'number'. +computedPropertyNames12_ES6.ts(9,5): error TS2411: Property '[+s]' of type 'string' is not assignable to 'string' index type 'number'. computedPropertyNames12_ES6.ts(12,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. computedPropertyNames12_ES6.ts(13,12): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. computedPropertyNames12_ES6.ts(15,12): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. -==== computedPropertyNames12_ES6.ts (8 errors) ==== +==== computedPropertyNames12_ES6.ts (10 errors) ==== var s: string; var n: number; var a: any; @@ -28,6 +30,10 @@ computedPropertyNames12_ES6.ts(15,12): error TS1166: A computed property name in [+s]: typeof s; ~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. + ~~~~ +!!! error TS2411: Property '[+s]' of type 'string' is not assignable to 'number' index type 'number'. + ~~~~ +!!! error TS2411: Property '[+s]' of type 'string' is not assignable to 'string' index type 'number'. static [""]: number; [0]: number; [a]: number; diff --git a/tests/baselines/reference/computedPropertyNames2_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames2_ES5.errors.txt index 2d1b4f1abc814..7f438a78ae85f 100644 --- a/tests/baselines/reference/computedPropertyNames2_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNames2_ES5.errors.txt @@ -1,8 +1,9 @@ computedPropertyNames2_ES5.ts(6,9): error TS2378: A 'get' accessor must return a value. +computedPropertyNames2_ES5.ts(6,9): error TS2411: Property '[accessorName]' of type 'void' is not assignable to 'string' index type '() => void'. computedPropertyNames2_ES5.ts(8,16): error TS2378: A 'get' accessor must return a value. -==== computedPropertyNames2_ES5.ts (2 errors) ==== +==== computedPropertyNames2_ES5.ts (3 errors) ==== var methodName = "method"; var accessorName = "accessor"; class C { @@ -11,6 +12,8 @@ computedPropertyNames2_ES5.ts(8,16): error TS2378: A 'get' accessor must return get [accessorName]() { } ~~~~~~~~~~~~~~ !!! error TS2378: A 'get' accessor must return a value. + ~~~~~~~~~~~~~~ +!!! error TS2411: Property '[accessorName]' of type 'void' is not assignable to 'string' index type '() => void'. set [accessorName](v) { } static get [accessorName]() { } ~~~~~~~~~~~~~~ diff --git a/tests/baselines/reference/computedPropertyNames2_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames2_ES6.errors.txt index e9f4abaf8f56a..bdf812aaf93d7 100644 --- a/tests/baselines/reference/computedPropertyNames2_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNames2_ES6.errors.txt @@ -1,8 +1,9 @@ computedPropertyNames2_ES6.ts(6,9): error TS2378: A 'get' accessor must return a value. +computedPropertyNames2_ES6.ts(6,9): error TS2411: Property '[accessorName]' of type 'void' is not assignable to 'string' index type '() => void'. computedPropertyNames2_ES6.ts(8,16): error TS2378: A 'get' accessor must return a value. -==== computedPropertyNames2_ES6.ts (2 errors) ==== +==== computedPropertyNames2_ES6.ts (3 errors) ==== var methodName = "method"; var accessorName = "accessor"; class C { @@ -11,6 +12,8 @@ computedPropertyNames2_ES6.ts(8,16): error TS2378: A 'get' accessor must return get [accessorName]() { } ~~~~~~~~~~~~~~ !!! error TS2378: A 'get' accessor must return a value. + ~~~~~~~~~~~~~~ +!!! error TS2411: Property '[accessorName]' of type 'void' is not assignable to 'string' index type '() => void'. set [accessorName](v) { } static get [accessorName]() { } ~~~~~~~~~~~~~~ diff --git a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt index 466c66649665c..5e36265fb4766 100644 --- a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt +++ b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt @@ -1,12 +1,14 @@ computedPropertyNamesWithStaticProperty.ts(3,10): error TS2449: Class 'C1' used before its declaration. computedPropertyNamesWithStaticProperty.ts(6,10): error TS2449: Class 'C1' used before its declaration. +computedPropertyNamesWithStaticProperty.ts(9,5): error TS2411: Property '[C1.staticProp]' of type '() => void' is not assignable to 'number' index type 'string'. computedPropertyNamesWithStaticProperty.ts(9,6): error TS2449: Class 'C1' used before its declaration. computedPropertyNamesWithStaticProperty.ts(14,10): error TS2449: Class 'C2' used before its declaration. computedPropertyNamesWithStaticProperty.ts(17,10): error TS2449: Class 'C2' used before its declaration. +computedPropertyNamesWithStaticProperty.ts(20,5): error TS2411: Property '[C2.staticProp]' of type '() => void' is not assignable to 'number' index type 'string'. computedPropertyNamesWithStaticProperty.ts(20,6): error TS2449: Class 'C2' used before its declaration. -==== computedPropertyNamesWithStaticProperty.ts (6 errors) ==== +==== computedPropertyNamesWithStaticProperty.ts (8 errors) ==== class C1 { static staticProp = 10; get [C1.staticProp]() { @@ -22,6 +24,8 @@ computedPropertyNamesWithStaticProperty.ts(20,6): error TS2449: Class 'C2' used var y = x; } [C1.staticProp]() { } + ~~~~~~~~~~~~~~~ +!!! error TS2411: Property '[C1.staticProp]' of type '() => void' is not assignable to 'number' index type 'string'. ~~ !!! error TS2449: Class 'C1' used before its declaration. !!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C1' is declared here. @@ -42,6 +46,8 @@ computedPropertyNamesWithStaticProperty.ts(20,6): error TS2449: Class 'C2' used var y = x; } [C2.staticProp]() { } + ~~~~~~~~~~~~~~~ +!!! error TS2411: Property '[C2.staticProp]' of type '() => void' is not assignable to 'number' index type 'string'. ~~ !!! error TS2449: Class 'C2' used before its declaration. !!! related TS2728 computedPropertyNamesWithStaticProperty.ts:12:8: 'C2' is declared here. diff --git a/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt b/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt index 90ceb463b9ce6..8a577dfa9eac3 100644 --- a/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt +++ b/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt @@ -7,25 +7,31 @@ isolatedDeclarationErrorsClasses.ts(11,9): error TS9009: At least one accessor m isolatedDeclarationErrorsClasses.ts(12,9): error TS7032: Property 'setOnly' implicitly has type 'any', because its set accessor lacks a parameter type annotation. isolatedDeclarationErrorsClasses.ts(12,17): error TS7006: Parameter 'value' implicitly has an 'any' type. isolatedDeclarationErrorsClasses.ts(36,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. +isolatedDeclarationErrorsClasses.ts(36,5): error TS2411: Property '[missing]' of type 'number' is not assignable to 'string' index type '() => void'. isolatedDeclarationErrorsClasses.ts(36,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(36,6): error TS2304: Cannot find name 'missing'. isolatedDeclarationErrorsClasses.ts(38,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +isolatedDeclarationErrorsClasses.ts(40,5): error TS2411: Property '[noParamAnnotationLiteralName]' of type '(v: string) => void' is not assignable to 'string' index type '() => void'. isolatedDeclarationErrorsClasses.ts(40,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(42,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +isolatedDeclarationErrorsClasses.ts(44,5): error TS2411: Property '[noParamAnnotationStringName]' of type '(v: any) => void' is not assignable to 'string' index type '() => void'. isolatedDeclarationErrorsClasses.ts(44,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(44,35): error TS7006: Parameter 'v' implicitly has an 'any' type. +isolatedDeclarationErrorsClasses.ts(46,9): error TS2411: Property '[noAnnotationStringName]' of type 'number' is not assignable to 'string' index type '() => void'. isolatedDeclarationErrorsClasses.ts(46,9): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(48,9): error TS7032: Property '[noParamAnnotationStringName]' implicitly has type 'any', because its set accessor lacks a parameter type annotation. isolatedDeclarationErrorsClasses.ts(48,9): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(48,39): error TS7006: Parameter 'value' implicitly has an 'any' type. isolatedDeclarationErrorsClasses.ts(50,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. +isolatedDeclarationErrorsClasses.ts(50,5): error TS2411: Property '[("A" + "B") as "AB"]' of type 'number' is not assignable to 'string' index type '() => void'. isolatedDeclarationErrorsClasses.ts(50,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(55,5): error TS1169: A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type. +isolatedDeclarationErrorsClasses.ts(56,5): error TS2411: Property '[noAnnotationLiteralName]' of type '() => any' is not assignable to 'string' index type '10'. isolatedDeclarationErrorsClasses.ts(56,5): error TS7010: '[noAnnotationLiteralName]', which lacks return-type annotation, implicitly has an 'any' return type. isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't be inferred with --isolatedDeclarations. -==== isolatedDeclarationErrorsClasses.ts (25 errors) ==== +==== isolatedDeclarationErrorsClasses.ts (31 errors) ==== export class Cls { field = 1 + 1; @@ -86,6 +92,8 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't b ~~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~~~~~~ +!!! error TS2411: Property '[missing]' of type 'number' is not assignable to 'string' index type '() => void'. + ~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. ~~~~~~~ !!! error TS2304: Cannot find name 'missing'. @@ -96,6 +104,8 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't b [noParamAnnotationLiteralName](v: string): void { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property '[noParamAnnotationLiteralName]' of type '(v: string) => void' is not assignable to 'string' index type '() => void'. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. [noAnnotationStringName]() { } @@ -104,12 +114,16 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't b [noParamAnnotationStringName](v): void { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property '[noParamAnnotationStringName]' of type '(v: any) => void' is not assignable to 'string' index type '() => void'. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. ~ !!! error TS7006: Parameter 'v' implicitly has an 'any' type. get [noAnnotationStringName]() { return 0;} ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property '[noAnnotationStringName]' of type 'number' is not assignable to 'string' index type '() => void'. + ~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. set [noParamAnnotationStringName](value) { } @@ -124,6 +138,8 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't b ~~~~~~~~~~~~~~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property '[("A" + "B") as "AB"]' of type 'number' is not assignable to 'string' index type '() => void'. + ~~~~~~~~~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. } @@ -134,6 +150,8 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't b !!! error TS1169: A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type. [noAnnotationLiteralName](); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property '[noAnnotationLiteralName]' of type '() => any' is not assignable to 'string' index type '10'. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS7010: '[noAnnotationLiteralName]', which lacks return-type annotation, implicitly has an 'any' return type. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS9013: Expression type can't be inferred with --isolatedDeclarations. diff --git a/tests/baselines/reference/superSymbolIndexedAccess1.types b/tests/baselines/reference/superSymbolIndexedAccess1.types index 122a3be1e875c..176a2b2cacfd4 100644 --- a/tests/baselines/reference/superSymbolIndexedAccess1.types +++ b/tests/baselines/reference/superSymbolIndexedAccess1.types @@ -38,14 +38,16 @@ class Bar extends Foo { > : ^^^ [symbol]() { ->[symbol] : () => any -> : ^^^^^^^^^ +>[symbol] : () => number +> : ^^^^^^^^^^^^ >symbol : symbol > : ^^^^^^ return super[symbol](); ->super[symbol]() : error ->super[symbol] : error +>super[symbol]() : number +> : ^^^^^^ +>super[symbol] : () => number +> : ^^^^^^^^^^^^ >super : Foo > : ^^^ >symbol : symbol From b49bf3c422e4c8982420cd668f203c2592359982 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 4 Sep 2024 15:52:37 -0700 Subject: [PATCH 3/8] Declaration emit support for late bound index signatures --- src/compiler/checker.ts | 22 +++++++++++++++++++ src/compiler/transformers/declarations.ts | 4 +++- src/compiler/types.ts | 1 + ...ssNonUniqueSymbolMethodHasSymbolIndexer.js | 1 + 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c6d9bd69acd70..269f6cbcee676 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1122,6 +1122,7 @@ import { WithStatement, YieldExpression, isIndexSignatureDeclaration, + MutableNodeArray, } from "./_namespaces/ts.js"; import * as moduleSpecifiers from "./_namespaces/ts.moduleSpecifiers.js"; import * as performance from "./_namespaces/ts.performance.js"; @@ -50495,6 +50496,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }, isImportRequiredByAugmentation, isDefinitelyReferenceToGlobalSymbolObject, + createLateBoundIndexSignatures: (cls, enclosing, flags, internalFlags, tracker) => { + const sym = cls.symbol; + const staticInfos = getIndexInfosOfType(getTypeOfSymbol(sym)); + const instanceIndexSymbol = getIndexSymbol(sym); + const instanceInfos = instanceIndexSymbol && getIndexInfosOfIndexSymbol(instanceIndexSymbol); + let result; + for (const infoList of [staticInfos, instanceInfos]) { + if (!length(infoList)) continue; + result ||= []; + for (const info of infoList!) { + const node = nodeBuilder.indexInfoToIndexSignatureDeclaration(info, enclosing, flags, internalFlags, tracker); + if (node && infoList === staticInfos) { + (((node as Mutable).modifiers ||= factory.createNodeArray()) as MutableNodeArray).unshift(factory.createModifier(SyntaxKind.StaticKeyword)); + } + if (node) { + result.push(node); + } + } + } + return result; + }, }; function isImportRequiredByAugmentation(node: ImportDeclaration) { diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index b12c3acf84c3e..da0c2dc15b705 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -12,6 +12,7 @@ import { canHaveModifiers, canProduceDiagnostics, ClassDeclaration, + ClassElement, compact, concatenate, ConditionalTypeNode, @@ -1654,7 +1655,8 @@ export function transformDeclarations(context: TransformationContext) { /*initializer*/ undefined, ), ] : undefined; - const memberNodes = concatenate(concatenate(privateIdentifier, parameterProperties), visitNodes(input.members, visitDeclarationSubtree, isClassElement)); + const lateIndexes = resolver.createLateBoundIndexSignatures(input, enclosingDeclaration, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker); + const memberNodes = concatenate(concatenate(concatenate(privateIdentifier, lateIndexes), parameterProperties), visitNodes(input.members, visitDeclarationSubtree, isClassElement)); const members = factory.createNodeArray(memberNodes); const extendsClause = getEffectiveBaseTypeNode(input); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7a7652eece24d..a9852b8ed5be3 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5866,6 +5866,7 @@ export interface EmitResolver { getDeclarationStatementsForSourceFile(node: SourceFile, flags: NodeBuilderFlags, internalFlags: InternalNodeBuilderFlags, tracker: SymbolTracker): Statement[] | undefined; isImportRequiredByAugmentation(decl: ImportDeclaration): boolean; isDefinitelyReferenceToGlobalSymbolObject(node: Node): boolean; + createLateBoundIndexSignatures(cls: ClassLikeDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, internalFlags: InternalNodeBuilderFlags, tracker: SymbolTracker): IndexSignatureDeclaration[] | undefined; } // dprint-ignore diff --git a/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.js b/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.js index e52b25c702203..b62a61483a00d 100644 --- a/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.js +++ b/tests/baselines/reference/classNonUniqueSymbolMethodHasSymbolIndexer.js @@ -28,6 +28,7 @@ export const Mixer = Mix(class { //// [classNonUniqueSymbolMethodHasSymbolIndexer.d.ts] export declare class A { + [x: symbol]: () => number; } export declare const Mixer: { new (): { From 57150e56f1371018fe63fa6e20c36c88450df3d6 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 4 Sep 2024 16:00:15 -0700 Subject: [PATCH 4/8] Support declaration emit --- src/compiler/checker.ts | 1 + src/compiler/emitter.ts | 1 + .../reference/isolatedDeclarationErrorsClasses.errors.txt | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 269f6cbcee676..36f4ad8f5bb7d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -50506,6 +50506,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!length(infoList)) continue; result ||= []; for (const info of infoList!) { + if (info.declaration) continue; const node = nodeBuilder.indexInfoToIndexSignatureDeclaration(info, enclosing, flags, internalFlags, tracker); if (node && infoList === staticInfos) { (((node as Mutable).modifiers ||= factory.createNodeArray()) as MutableNodeArray).unshift(factory.createModifier(SyntaxKind.StaticKeyword)); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 98f42996cc86c..13021670dc7be 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1163,6 +1163,7 @@ export const notImplementedResolver: EmitResolver = { getDeclarationStatementsForSourceFile: notImplemented, isImportRequiredByAugmentation: notImplemented, isDefinitelyReferenceToGlobalSymbolObject: notImplemented, + createLateBoundIndexSignatures: notImplemented, }; const enum PipelinePhase { diff --git a/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt b/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt index 8a577dfa9eac3..f23a18cfca814 100644 --- a/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt +++ b/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt @@ -1,3 +1,4 @@ +error TS-1: Pre-emit (32) and post-emit (31) diagnostic counts do not match! This can indicate that a semantic _error_ was added by the emit resolver - such an error may not be reflected on the command line or in the editor, but may be captured in a baseline here! isolatedDeclarationErrorsClasses.ts(3,5): error TS9012: Property must have an explicit type annotation with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(4,5): error TS9008: Method must have an explicit return type annotation with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(8,18): error TS7006: Parameter 'p' implicitly has an 'any' type. @@ -31,6 +32,9 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS7010: '[noAnnotationLiteralNa isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't be inferred with --isolatedDeclarations. +!!! error TS-1: Pre-emit (32) and post-emit (31) diagnostic counts do not match! This can indicate that a semantic _error_ was added by the emit resolver - such an error may not be reflected on the command line or in the editor, but may be captured in a baseline here! +!!! related TS-1: The excess diagnostics are: +!!! related TS9008 isolatedDeclarationErrorsClasses.ts:42:5: Method must have an explicit return type annotation with --isolatedDeclarations. ==== isolatedDeclarationErrorsClasses.ts (31 errors) ==== export class Cls { From 9cbe32a36dfbe53c128a544c4ed01769652266ae Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 4 Sep 2024 16:36:27 -0700 Subject: [PATCH 5/8] Format --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 36f4ad8f5bb7d..b93e1f49d2c64 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -583,6 +583,7 @@ import { isImportTypeNode, isInCompoundLikeAssignment, isIndexedAccessTypeNode, + isIndexSignatureDeclaration, isInExpressionContext, isInfinityOrNaNString, isInitializedProperty, @@ -878,6 +879,7 @@ import { ModuleResolutionKind, ModuleSpecifierResolutionHost, Mutable, + MutableNodeArray, NamedDeclaration, NamedExports, NamedImportsOrExports, @@ -1121,8 +1123,6 @@ import { WideningContext, WithStatement, YieldExpression, - isIndexSignatureDeclaration, - MutableNodeArray, } from "./_namespaces/ts.js"; import * as moduleSpecifiers from "./_namespaces/ts.moduleSpecifiers.js"; import * as performance from "./_namespaces/ts.performance.js"; From eb0437a6bae40e67006a14944ca9dc0673cc7bdb Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 9 Sep 2024 13:30:44 -0700 Subject: [PATCH 6/8] Use identical logic for type/class implied index signatures and object literal expressions --- src/compiler/checker.ts | 61 +++++++++++++------ .../reference/ES5SymbolProperty2.types | 8 +-- .../reference/ES5SymbolProperty3.types | 3 +- .../reference/ES5SymbolProperty6.types | 4 +- .../reference/ES5SymbolProperty7.types | 3 +- ...pturedParametersInInitializers2.errors.txt | 5 +- .../reference/complicatedPrivacy.types | 4 +- .../computedPropertyNames2_ES5.errors.txt | 5 +- .../computedPropertyNames2_ES6.errors.txt | 5 +- ...PropertyNamesWithStaticProperty.errors.txt | 8 +-- ...clarationEmitAnyComputedPropertyInClass.js | 1 + ...arationEmitComputedPropertyNameEnum2.types | 4 +- ...solatedDeclarationErrorsClasses.errors.txt | 21 +------ .../parserComputedPropertyName13.types | 4 +- .../parserComputedPropertyName14.types | 4 +- .../parserComputedPropertyName18.types | 4 +- .../parserComputedPropertyName19.types | 4 +- .../parserES5ComputedPropertyName8.types | 4 +- .../reference/parserES5SymbolProperty8.types | 4 +- .../reference/parserES5SymbolProperty9.types | 4 +- .../reference/propertyAssignment.types | 8 +-- .../reference/superSymbolIndexedAccess5.types | 10 +-- .../reference/superSymbolIndexedAccess6.types | 10 +-- .../declarationComputedPropertyNames.d.ts | 1 + 24 files changed, 93 insertions(+), 96 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b93e1f49d2c64..b816be5a1c9d5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16255,9 +16255,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return indexSymbol ? getIndexInfosOfIndexSymbol(indexSymbol) : emptyArray; } + // note intentional similarities to index signature building in `checkObjectLiteral` for parity function getIndexInfosOfIndexSymbol(indexSymbol: Symbol): IndexInfo[] { if (indexSymbol.declarations) { const indexInfos: IndexInfo[] = []; + let hasComputedNumberProperty = false; + let readonlyComputedNumberProperty = true; + let hasComputedSymbolProperty = false; + let readonlyComputedSymbolProperty = true; + let hasComputedStringProperty = false; + let readonlyComputedStringProperty = true; + const computedPropertySymbols: Symbol[] = []; for (const declaration of indexSymbol.declarations) { if (isIndexSignatureDeclaration(declaration)) { if (declaration.parameters.length === 1) { @@ -16272,25 +16280,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else if (hasLateBindableIndexSignature(declaration)) { - // TODO: Combine index signatures inferred for each member? Or make an index info for each? - // Combined? - // Pros: Easily made, definite compatability with all relevant signatures. - // Cons: Unspecific. Can't make the signature until all declarations are processed - // Individual? - // Pros: Can inject one at a time. Accurate read types via index info applicability filtering. - // Cons: Can't tell at-a-glance which signatures apply? Potentially lots of signatures to track? - // Individual probably better, so is what we do here. - const declName = isBinaryExpression(declaration) ? declaration.left as ElementAccessExpression : (declaration as LateBoundDeclaration).name; const keyType = isElementAccessExpression(declName) ? checkExpressionCached(declName.argumentExpression) : checkComputedPropertyName(declName); - forEachType(keyType, keyType => { - // First-in-wins on multiple declarations right now - combine? leave as multiple, but with compatability error? - if (isValidIndexKeyType(keyType) && !findIndexInfo(indexInfos, keyType)) { - indexInfos.push(createIndexInfo(keyType, getTypeOfVariableOrParameterOrProperty(declaration.symbol), hasEffectiveModifier(declaration, ModifierFlags.Readonly))); + if (findIndexInfo(indexInfos, keyType)) { + continue; // Explicit index for key type takes priority + } + if (isTypeAssignableTo(keyType, stringNumberSymbolType)) { + if (isTypeAssignableTo(keyType, numberType)) { + hasComputedNumberProperty = true; + if (!hasEffectiveReadonlyModifier(declaration)) { + readonlyComputedNumberProperty = false; + } } - }); + else if (isTypeAssignableTo(keyType, esSymbolType)) { + hasComputedSymbolProperty = true; + if (!hasEffectiveReadonlyModifier(declaration)) { + readonlyComputedSymbolProperty = false; + } + } + else { + hasComputedStringProperty = true; + if (!hasEffectiveReadonlyModifier(declaration)) { + readonlyComputedStringProperty = false; + } + } + computedPropertySymbols.push(declaration.symbol); + } } } + // aggregate similar index infos implied to be the same key to the same combined index info + if (hasComputedStringProperty && !findIndexInfo(indexInfos, stringType)) indexInfos.push(getObjectLiteralIndexInfo(readonlyComputedStringProperty, 0, computedPropertySymbols, stringType)); + if (hasComputedNumberProperty && !findIndexInfo(indexInfos, numberType)) indexInfos.push(getObjectLiteralIndexInfo(readonlyComputedNumberProperty, 0, computedPropertySymbols, numberType)); + if (hasComputedSymbolProperty && !findIndexInfo(indexInfos, esSymbolType)) indexInfos.push(getObjectLiteralIndexInfo(readonlyComputedSymbolProperty, 0, computedPropertySymbols, esSymbolType)); return indexInfos; } return emptyArray; @@ -32858,7 +32879,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { isTypeAssignableToKind(checkComputedPropertyName(firstDecl.name), TypeFlags.ESSymbol)); } - function getObjectLiteralIndexInfo(node: ObjectLiteralExpression, offset: number, properties: Symbol[], keyType: Type): IndexInfo { + // NOTE: currently does not make pattern literal indexers, eg `${number}px` + function getObjectLiteralIndexInfo(isReadonly: boolean, offset: number, properties: Symbol[], keyType: Type): IndexInfo { const propTypes: Type[] = []; for (let i = offset; i < properties.length; i++) { const prop = properties[i]; @@ -32871,7 +32893,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } const unionType = propTypes.length ? getUnionType(propTypes, UnionReduction.Subtype) : undefinedType; - return createIndexInfo(keyType, unionType, isConstContext(node)); + return createIndexInfo(keyType, unionType, isReadonly); } function getImmediateAliasedSymbol(symbol: Symbol): Symbol | undefined { @@ -33076,9 +33098,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function createObjectLiteralType() { const indexInfos = []; - if (hasComputedStringProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, stringType)); - if (hasComputedNumberProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, numberType)); - if (hasComputedSymbolProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, esSymbolType)); + const isReadonly = isConstContext(node); + if (hasComputedStringProperty) indexInfos.push(getObjectLiteralIndexInfo(isReadonly, offset, propertiesArray, stringType)); + if (hasComputedNumberProperty) indexInfos.push(getObjectLiteralIndexInfo(isReadonly, offset, propertiesArray, numberType)); + if (hasComputedSymbolProperty) indexInfos.push(getObjectLiteralIndexInfo(isReadonly, offset, propertiesArray, esSymbolType)); const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, indexInfos); result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral; if (isJSObjectLiteral) { diff --git a/tests/baselines/reference/ES5SymbolProperty2.types b/tests/baselines/reference/ES5SymbolProperty2.types index c3b8a051b1b0d..bb881741d6254 100644 --- a/tests/baselines/reference/ES5SymbolProperty2.types +++ b/tests/baselines/reference/ES5SymbolProperty2.types @@ -24,8 +24,8 @@ module M { > : ^^^ } (new C)[Symbol.iterator]; ->(new C)[Symbol.iterator] : any -> : ^^^ +>(new C)[Symbol.iterator] : () => void +> : ^^^^^^^^^^ >(new C) : C > : ^ >new C : C @@ -41,8 +41,8 @@ module M { } (new M.C)[Symbol.iterator]; ->(new M.C)[Symbol.iterator] : any -> : ^^^ +>(new M.C)[Symbol.iterator] : () => void +> : ^^^^^^^^^^ >(new M.C) : M.C > : ^^^ >new M.C : M.C diff --git a/tests/baselines/reference/ES5SymbolProperty3.types b/tests/baselines/reference/ES5SymbolProperty3.types index 406e96a719c2f..0a8427ac904eb 100644 --- a/tests/baselines/reference/ES5SymbolProperty3.types +++ b/tests/baselines/reference/ES5SymbolProperty3.types @@ -19,7 +19,8 @@ class C { } (new C)[Symbol.iterator] ->(new C)[Symbol.iterator] : error +>(new C)[Symbol.iterator] : () => void +> : ^^^^^^^^^^ >(new C) : C > : ^ >new C : C diff --git a/tests/baselines/reference/ES5SymbolProperty6.types b/tests/baselines/reference/ES5SymbolProperty6.types index f4485046d83a1..7b2b3329ec082 100644 --- a/tests/baselines/reference/ES5SymbolProperty6.types +++ b/tests/baselines/reference/ES5SymbolProperty6.types @@ -17,8 +17,8 @@ class C { } (new C)[Symbol.iterator] ->(new C)[Symbol.iterator] : any -> : ^^^ +>(new C)[Symbol.iterator] : () => void +> : ^^^^^^^^^^ >(new C) : C > : ^ >new C : C diff --git a/tests/baselines/reference/ES5SymbolProperty7.types b/tests/baselines/reference/ES5SymbolProperty7.types index 324525e5ca3ca..15b9cc28809f0 100644 --- a/tests/baselines/reference/ES5SymbolProperty7.types +++ b/tests/baselines/reference/ES5SymbolProperty7.types @@ -21,7 +21,8 @@ class C { } (new C)[Symbol.iterator] ->(new C)[Symbol.iterator] : error +>(new C)[Symbol.iterator] : () => void +> : ^^^^^^^^^^ >(new C) : C > : ^ >new C : C diff --git a/tests/baselines/reference/capturedParametersInInitializers2.errors.txt b/tests/baselines/reference/capturedParametersInInitializers2.errors.txt index c190ffe48f335..7f7e502bfbba2 100644 --- a/tests/baselines/reference/capturedParametersInInitializers2.errors.txt +++ b/tests/baselines/reference/capturedParametersInInitializers2.errors.txt @@ -1,12 +1,11 @@ capturedParametersInInitializers2.ts(3,20): error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. capturedParametersInInitializers2.ts(4,14): error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. -capturedParametersInInitializers2.ts(6,9): error TS2411: Property '[z]' of type '() => number' is not assignable to 'number' index type 'number'. capturedParametersInInitializers2.ts(6,10): error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. capturedParametersInInitializers2.ts(13,26): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. capturedParametersInInitializers2.ts(13,27): error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. -==== capturedParametersInInitializers2.ts (6 errors) ==== +==== capturedParametersInInitializers2.ts (5 errors) ==== function foo( y = class { static c = x; @@ -17,8 +16,6 @@ capturedParametersInInitializers2.ts(13,27): error TS2373: Parameter 'y' cannot !!! error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. constructor() { x; } [z]() { return z; } - ~~~ -!!! error TS2411: Property '[z]' of type '() => number' is not assignable to 'number' index type 'number'. ~ !!! error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. }, diff --git a/tests/baselines/reference/complicatedPrivacy.types b/tests/baselines/reference/complicatedPrivacy.types index d9fd54eb04428..d0ff49fdceaa8 100644 --- a/tests/baselines/reference/complicatedPrivacy.types +++ b/tests/baselines/reference/complicatedPrivacy.types @@ -86,8 +86,8 @@ module m1 { export function f4(arg1: >f4 : (arg1: { [number]: C1; }) => void > : ^ ^^ ^^^^^^^^^ ->arg1 : {} -> : ^^ +>arg1 : { [x: number]: C1; } +> : ^^^^^^^^^^^^^^^^^^^^ { [number]: C1; // Used to be indexer, now it is a computed property >[number] : C1 diff --git a/tests/baselines/reference/computedPropertyNames2_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames2_ES5.errors.txt index 7f438a78ae85f..2d1b4f1abc814 100644 --- a/tests/baselines/reference/computedPropertyNames2_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNames2_ES5.errors.txt @@ -1,9 +1,8 @@ computedPropertyNames2_ES5.ts(6,9): error TS2378: A 'get' accessor must return a value. -computedPropertyNames2_ES5.ts(6,9): error TS2411: Property '[accessorName]' of type 'void' is not assignable to 'string' index type '() => void'. computedPropertyNames2_ES5.ts(8,16): error TS2378: A 'get' accessor must return a value. -==== computedPropertyNames2_ES5.ts (3 errors) ==== +==== computedPropertyNames2_ES5.ts (2 errors) ==== var methodName = "method"; var accessorName = "accessor"; class C { @@ -12,8 +11,6 @@ computedPropertyNames2_ES5.ts(8,16): error TS2378: A 'get' accessor must return get [accessorName]() { } ~~~~~~~~~~~~~~ !!! error TS2378: A 'get' accessor must return a value. - ~~~~~~~~~~~~~~ -!!! error TS2411: Property '[accessorName]' of type 'void' is not assignable to 'string' index type '() => void'. set [accessorName](v) { } static get [accessorName]() { } ~~~~~~~~~~~~~~ diff --git a/tests/baselines/reference/computedPropertyNames2_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames2_ES6.errors.txt index bdf812aaf93d7..e9f4abaf8f56a 100644 --- a/tests/baselines/reference/computedPropertyNames2_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNames2_ES6.errors.txt @@ -1,9 +1,8 @@ computedPropertyNames2_ES6.ts(6,9): error TS2378: A 'get' accessor must return a value. -computedPropertyNames2_ES6.ts(6,9): error TS2411: Property '[accessorName]' of type 'void' is not assignable to 'string' index type '() => void'. computedPropertyNames2_ES6.ts(8,16): error TS2378: A 'get' accessor must return a value. -==== computedPropertyNames2_ES6.ts (3 errors) ==== +==== computedPropertyNames2_ES6.ts (2 errors) ==== var methodName = "method"; var accessorName = "accessor"; class C { @@ -12,8 +11,6 @@ computedPropertyNames2_ES6.ts(8,16): error TS2378: A 'get' accessor must return get [accessorName]() { } ~~~~~~~~~~~~~~ !!! error TS2378: A 'get' accessor must return a value. - ~~~~~~~~~~~~~~ -!!! error TS2411: Property '[accessorName]' of type 'void' is not assignable to 'string' index type '() => void'. set [accessorName](v) { } static get [accessorName]() { } ~~~~~~~~~~~~~~ diff --git a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt index 5e36265fb4766..466c66649665c 100644 --- a/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt +++ b/tests/baselines/reference/computedPropertyNamesWithStaticProperty.errors.txt @@ -1,14 +1,12 @@ computedPropertyNamesWithStaticProperty.ts(3,10): error TS2449: Class 'C1' used before its declaration. computedPropertyNamesWithStaticProperty.ts(6,10): error TS2449: Class 'C1' used before its declaration. -computedPropertyNamesWithStaticProperty.ts(9,5): error TS2411: Property '[C1.staticProp]' of type '() => void' is not assignable to 'number' index type 'string'. computedPropertyNamesWithStaticProperty.ts(9,6): error TS2449: Class 'C1' used before its declaration. computedPropertyNamesWithStaticProperty.ts(14,10): error TS2449: Class 'C2' used before its declaration. computedPropertyNamesWithStaticProperty.ts(17,10): error TS2449: Class 'C2' used before its declaration. -computedPropertyNamesWithStaticProperty.ts(20,5): error TS2411: Property '[C2.staticProp]' of type '() => void' is not assignable to 'number' index type 'string'. computedPropertyNamesWithStaticProperty.ts(20,6): error TS2449: Class 'C2' used before its declaration. -==== computedPropertyNamesWithStaticProperty.ts (8 errors) ==== +==== computedPropertyNamesWithStaticProperty.ts (6 errors) ==== class C1 { static staticProp = 10; get [C1.staticProp]() { @@ -24,8 +22,6 @@ computedPropertyNamesWithStaticProperty.ts(20,6): error TS2449: Class 'C2' used var y = x; } [C1.staticProp]() { } - ~~~~~~~~~~~~~~~ -!!! error TS2411: Property '[C1.staticProp]' of type '() => void' is not assignable to 'number' index type 'string'. ~~ !!! error TS2449: Class 'C1' used before its declaration. !!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C1' is declared here. @@ -46,8 +42,6 @@ computedPropertyNamesWithStaticProperty.ts(20,6): error TS2449: Class 'C2' used var y = x; } [C2.staticProp]() { } - ~~~~~~~~~~~~~~~ -!!! error TS2411: Property '[C2.staticProp]' of type '() => void' is not assignable to 'number' index type 'string'. ~~ !!! error TS2449: Class 'C2' used before its declaration. !!! related TS2728 computedPropertyNamesWithStaticProperty.ts:12:8: 'C2' is declared here. diff --git a/tests/baselines/reference/declarationEmitAnyComputedPropertyInClass.js b/tests/baselines/reference/declarationEmitAnyComputedPropertyInClass.js index c7d96ee96e0be..bc3473ad4d914 100644 --- a/tests/baselines/reference/declarationEmitAnyComputedPropertyInClass.js +++ b/tests/baselines/reference/declarationEmitAnyComputedPropertyInClass.js @@ -28,4 +28,5 @@ exports.C = C; //// [main.d.ts] export declare class C { + [x: number]: () => void; } diff --git a/tests/baselines/reference/declarationEmitComputedPropertyNameEnum2.types b/tests/baselines/reference/declarationEmitComputedPropertyNameEnum2.types index 1e5e4b1c668a0..d1e82f6148633 100644 --- a/tests/baselines/reference/declarationEmitComputedPropertyNameEnum2.types +++ b/tests/baselines/reference/declarationEmitComputedPropertyNameEnum2.types @@ -4,8 +4,8 @@ export type Type = { x?: { [Enum.A]: 0 } }; >Type : Type > : ^^^^ ->x : {} | undefined -> : ^^^^^^^^^^^^^^ +>x : { [x: number]: 0; } | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >[Enum.A] : 0 > : ^ >Enum.A : any diff --git a/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt b/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt index f23a18cfca814..fd58e7f478d90 100644 --- a/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt +++ b/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt @@ -1,4 +1,3 @@ -error TS-1: Pre-emit (32) and post-emit (31) diagnostic counts do not match! This can indicate that a semantic _error_ was added by the emit resolver - such an error may not be reflected on the command line or in the editor, but may be captured in a baseline here! isolatedDeclarationErrorsClasses.ts(3,5): error TS9012: Property must have an explicit type annotation with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(4,5): error TS9008: Method must have an explicit return type annotation with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(8,18): error TS7006: Parameter 'p' implicitly has an 'any' type. @@ -8,23 +7,18 @@ isolatedDeclarationErrorsClasses.ts(11,9): error TS9009: At least one accessor m isolatedDeclarationErrorsClasses.ts(12,9): error TS7032: Property 'setOnly' implicitly has type 'any', because its set accessor lacks a parameter type annotation. isolatedDeclarationErrorsClasses.ts(12,17): error TS7006: Parameter 'value' implicitly has an 'any' type. isolatedDeclarationErrorsClasses.ts(36,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. -isolatedDeclarationErrorsClasses.ts(36,5): error TS2411: Property '[missing]' of type 'number' is not assignable to 'string' index type '() => void'. isolatedDeclarationErrorsClasses.ts(36,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(36,6): error TS2304: Cannot find name 'missing'. isolatedDeclarationErrorsClasses.ts(38,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -isolatedDeclarationErrorsClasses.ts(40,5): error TS2411: Property '[noParamAnnotationLiteralName]' of type '(v: string) => void' is not assignable to 'string' index type '() => void'. isolatedDeclarationErrorsClasses.ts(40,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(42,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -isolatedDeclarationErrorsClasses.ts(44,5): error TS2411: Property '[noParamAnnotationStringName]' of type '(v: any) => void' is not assignable to 'string' index type '() => void'. isolatedDeclarationErrorsClasses.ts(44,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(44,35): error TS7006: Parameter 'v' implicitly has an 'any' type. -isolatedDeclarationErrorsClasses.ts(46,9): error TS2411: Property '[noAnnotationStringName]' of type 'number' is not assignable to 'string' index type '() => void'. isolatedDeclarationErrorsClasses.ts(46,9): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(48,9): error TS7032: Property '[noParamAnnotationStringName]' implicitly has type 'any', because its set accessor lacks a parameter type annotation. isolatedDeclarationErrorsClasses.ts(48,9): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(48,39): error TS7006: Parameter 'value' implicitly has an 'any' type. isolatedDeclarationErrorsClasses.ts(50,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. -isolatedDeclarationErrorsClasses.ts(50,5): error TS2411: Property '[("A" + "B") as "AB"]' of type 'number' is not assignable to 'string' index type '() => void'. isolatedDeclarationErrorsClasses.ts(50,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(55,5): error TS1169: A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type. isolatedDeclarationErrorsClasses.ts(56,5): error TS2411: Property '[noAnnotationLiteralName]' of type '() => any' is not assignable to 'string' index type '10'. @@ -32,10 +26,7 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS7010: '[noAnnotationLiteralNa isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't be inferred with --isolatedDeclarations. -!!! error TS-1: Pre-emit (32) and post-emit (31) diagnostic counts do not match! This can indicate that a semantic _error_ was added by the emit resolver - such an error may not be reflected on the command line or in the editor, but may be captured in a baseline here! -!!! related TS-1: The excess diagnostics are: -!!! related TS9008 isolatedDeclarationErrorsClasses.ts:42:5: Method must have an explicit return type annotation with --isolatedDeclarations. -==== isolatedDeclarationErrorsClasses.ts (31 errors) ==== +==== isolatedDeclarationErrorsClasses.ts (26 errors) ==== export class Cls { field = 1 + 1; @@ -96,8 +87,6 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't b ~~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~~~~~~ -!!! error TS2411: Property '[missing]' of type 'number' is not assignable to 'string' index type '() => void'. - ~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. ~~~~~~~ !!! error TS2304: Cannot find name 'missing'. @@ -108,8 +97,6 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't b [noParamAnnotationLiteralName](v: string): void { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property '[noParamAnnotationLiteralName]' of type '(v: string) => void' is not assignable to 'string' index type '() => void'. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. [noAnnotationStringName]() { } @@ -118,16 +105,12 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't b [noParamAnnotationStringName](v): void { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property '[noParamAnnotationStringName]' of type '(v: any) => void' is not assignable to 'string' index type '() => void'. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. ~ !!! error TS7006: Parameter 'v' implicitly has an 'any' type. get [noAnnotationStringName]() { return 0;} ~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property '[noAnnotationStringName]' of type 'number' is not assignable to 'string' index type '() => void'. - ~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. set [noParamAnnotationStringName](value) { } @@ -142,8 +125,6 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't b ~~~~~~~~~~~~~~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property '[("A" + "B") as "AB"]' of type 'number' is not assignable to 'string' index type '() => void'. - ~~~~~~~~~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. } diff --git a/tests/baselines/reference/parserComputedPropertyName13.types b/tests/baselines/reference/parserComputedPropertyName13.types index 6e99a4829fe25..0f33bd7c5f4a2 100644 --- a/tests/baselines/reference/parserComputedPropertyName13.types +++ b/tests/baselines/reference/parserComputedPropertyName13.types @@ -2,8 +2,8 @@ === parserComputedPropertyName13.ts === var v: { [e]: number }; ->v : {} -> : ^^ +>v : { [x: number]: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^ >[e] : number > : ^^^^^^ >e : any diff --git a/tests/baselines/reference/parserComputedPropertyName14.types b/tests/baselines/reference/parserComputedPropertyName14.types index 5678dc297079e..10fa63ce6fe05 100644 --- a/tests/baselines/reference/parserComputedPropertyName14.types +++ b/tests/baselines/reference/parserComputedPropertyName14.types @@ -2,8 +2,8 @@ === parserComputedPropertyName14.ts === var v: { [e](): number }; ->v : {} -> : ^^ +>v : { [x: number]: () => number; } +> : ^^^^^^^^^^^^^^^^^^^^^ ^^^ >[e] : () => number > : ^^^^^^ >e : any diff --git a/tests/baselines/reference/parserComputedPropertyName18.types b/tests/baselines/reference/parserComputedPropertyName18.types index 6cb139f89ae29..b4066ce95250b 100644 --- a/tests/baselines/reference/parserComputedPropertyName18.types +++ b/tests/baselines/reference/parserComputedPropertyName18.types @@ -2,8 +2,8 @@ === parserComputedPropertyName18.ts === var v: { [e]?(): number }; ->v : {} -> : ^^ +>v : { [x: number]: () => number; } +> : ^^^^^^^^^^^^^^^^^^^^^ ^^^ >[e] : () => number > : ^^^^^^ >e : any diff --git a/tests/baselines/reference/parserComputedPropertyName19.types b/tests/baselines/reference/parserComputedPropertyName19.types index 33ec268a9e308..ca0d674d53faf 100644 --- a/tests/baselines/reference/parserComputedPropertyName19.types +++ b/tests/baselines/reference/parserComputedPropertyName19.types @@ -2,8 +2,8 @@ === parserComputedPropertyName19.ts === var v: { [e]? }; ->v : {} -> : ^^ +>v : { [x: number]: any; } +> : ^^^^^^^^^^^^^^^^^^^^^ >[e] : any > : ^^^ >e : any diff --git a/tests/baselines/reference/parserES5ComputedPropertyName8.types b/tests/baselines/reference/parserES5ComputedPropertyName8.types index 15a66359e4b71..104894c313e2a 100644 --- a/tests/baselines/reference/parserES5ComputedPropertyName8.types +++ b/tests/baselines/reference/parserES5ComputedPropertyName8.types @@ -2,8 +2,8 @@ === parserES5ComputedPropertyName8.ts === var v: { [e]: number }; ->v : {} -> : ^^ +>v : { [x: number]: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^ >[e] : number > : ^^^^^^ >e : any diff --git a/tests/baselines/reference/parserES5SymbolProperty8.types b/tests/baselines/reference/parserES5SymbolProperty8.types index 1640d15ac08c8..ce13b98773f82 100644 --- a/tests/baselines/reference/parserES5SymbolProperty8.types +++ b/tests/baselines/reference/parserES5SymbolProperty8.types @@ -2,8 +2,8 @@ === parserES5SymbolProperty8.ts === var x: { ->x : {} -> : ^^ +>x : { [x: number]: () => string; } +> : ^^^^^^^^^^^^^^^^^^^^^ ^^^ [Symbol.toPrimitive](): string >[Symbol.toPrimitive] : () => string diff --git a/tests/baselines/reference/parserES5SymbolProperty9.types b/tests/baselines/reference/parserES5SymbolProperty9.types index d760467356cfa..1142830c03adb 100644 --- a/tests/baselines/reference/parserES5SymbolProperty9.types +++ b/tests/baselines/reference/parserES5SymbolProperty9.types @@ -2,8 +2,8 @@ === parserES5SymbolProperty9.ts === var x: { ->x : {} -> : ^^ +>x : { [x: number]: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^ [Symbol.toPrimitive]: string >[Symbol.toPrimitive] : string diff --git a/tests/baselines/reference/propertyAssignment.types b/tests/baselines/reference/propertyAssignment.types index c931d3d716091..f9f2a8bc55128 100644 --- a/tests/baselines/reference/propertyAssignment.types +++ b/tests/baselines/reference/propertyAssignment.types @@ -12,8 +12,8 @@ var bar1: { x : number; } > : ^^^^^^ var foo2: { [index]; } // should be an error, used to be indexer, now it is a computed property ->foo2 : {} -> : ^^ +>foo2 : { [x: number]: any; } +> : ^^^^^^^^^^^^^^^^^^^^^ >[index] : any > : ^^^ >index : any @@ -48,8 +48,8 @@ foo1 = bar1; // should be an error foo2 = bar2; >foo2 = bar2 : { x: number; } > : ^^^^^ ^^^ ->foo2 : {} -> : ^^ +>foo2 : { [x: number]: any; } +> : ^^^^^^^^^^^^^^^^^^^^^ >bar2 : { x: number; } > : ^^^^^ ^^^ diff --git a/tests/baselines/reference/superSymbolIndexedAccess5.types b/tests/baselines/reference/superSymbolIndexedAccess5.types index 0f4ba0f264fbb..26144f60740e4 100644 --- a/tests/baselines/reference/superSymbolIndexedAccess5.types +++ b/tests/baselines/reference/superSymbolIndexedAccess5.types @@ -26,13 +26,15 @@ class Bar extends Foo { > : ^^^ [symbol]() { ->[symbol] : () => any -> : ^^^^^^^^^ +>[symbol] : () => number +> : ^^^^^^^^^^^^ >symbol : any return super[symbol](); ->super[symbol]() : error ->super[symbol] : error +>super[symbol]() : number +> : ^^^^^^ +>super[symbol] : () => number +> : ^^^^^^^^^^^^ >super : Foo > : ^^^ >symbol : any diff --git a/tests/baselines/reference/superSymbolIndexedAccess6.types b/tests/baselines/reference/superSymbolIndexedAccess6.types index 619dbf1dabb1c..2c86a253d7f8c 100644 --- a/tests/baselines/reference/superSymbolIndexedAccess6.types +++ b/tests/baselines/reference/superSymbolIndexedAccess6.types @@ -26,13 +26,15 @@ class Bar extends Foo { > : ^^^ static [symbol]() { ->[symbol] : () => any -> : ^^^^^^^^^ +>[symbol] : () => number +> : ^^^^^^^^^^^^ >symbol : any return super[symbol](); ->super[symbol]() : error ->super[symbol] : error +>super[symbol]() : number +> : ^^^^^^ +>super[symbol] : () => number +> : ^^^^^^^^^^^^ >super : typeof Foo > : ^^^^^^^^^^ >symbol : any diff --git a/tests/baselines/reference/transpile/declarationComputedPropertyNames.d.ts b/tests/baselines/reference/transpile/declarationComputedPropertyNames.d.ts index 16e79cea6cedc..3c81cf66f0e84 100644 --- a/tests/baselines/reference/transpile/declarationComputedPropertyNames.d.ts +++ b/tests/baselines/reference/transpile/declarationComputedPropertyNames.d.ts @@ -86,6 +86,7 @@ export interface B { ["2"]: number; } export declare class C { + [x: number]: number; [Symbol.iterator]: number; [globalThis.Symbol.toStringTag]: number; [1]: number; From df020decba65a61787d20670b2e89d6d3011d542 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 9 Sep 2024 13:47:34 -0700 Subject: [PATCH 7/8] Note to self: swap fourslash quickinfo verify tests to baseline tests --- tests/cases/fourslash/quickInfoInInvalidIndexSignature.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/fourslash/quickInfoInInvalidIndexSignature.ts b/tests/cases/fourslash/quickInfoInInvalidIndexSignature.ts index 8205da6a31e0b..4096153db6fc5 100644 --- a/tests/cases/fourslash/quickInfoInInvalidIndexSignature.ts +++ b/tests/cases/fourslash/quickInfoInInvalidIndexSignature.ts @@ -2,4 +2,4 @@ //// function method() { var /**/dictionary = <{ [index]: string; }>{}; } -verify.quickInfoAt("", "(local var) dictionary: {}"); +verify.quickInfoAt("", "(local var) dictionary: {\n [x: number]: string;\n}"); From 708095aeae89361a956b147a8765f11355daae36 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 10 Sep 2024 13:06:40 -0700 Subject: [PATCH 8/8] Actually include the types of explicit properties in implies index signature types - cant forget those --- src/compiler/checker.ts | 15 ++++++++------- src/compiler/types.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- .../isolatedDeclarationErrorsClasses.errors.txt | 5 +---- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b816be5a1c9d5..b228860ab99e6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14207,7 +14207,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const indexSymbol = getIndexSymbolFromSymbolTable(members); if (indexSymbol) { - indexInfos = getIndexInfosOfIndexSymbol(indexSymbol); + indexInfos = getIndexInfosOfIndexSymbol(indexSymbol, arrayFrom(members.values())); } else { if (baseConstructorIndexInfo) { @@ -16252,11 +16252,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getIndexInfosOfSymbol(symbol: Symbol): IndexInfo[] { const indexSymbol = getIndexSymbol(symbol); - return indexSymbol ? getIndexInfosOfIndexSymbol(indexSymbol) : emptyArray; + return indexSymbol ? getIndexInfosOfIndexSymbol(indexSymbol, arrayFrom(getMembersOfSymbol(symbol).values())) : emptyArray; } // note intentional similarities to index signature building in `checkObjectLiteral` for parity - function getIndexInfosOfIndexSymbol(indexSymbol: Symbol): IndexInfo[] { + function getIndexInfosOfIndexSymbol(indexSymbol: Symbol, siblingSymbols: Symbol[] | undefined = indexSymbol.parent ? arrayFrom(getMembersOfSymbol(indexSymbol.parent).values()) : undefined): IndexInfo[] { if (indexSymbol.declarations) { const indexInfos: IndexInfo[] = []; let hasComputedNumberProperty = false; @@ -16308,10 +16308,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } + const allPropertySymbols = concatenate(computedPropertySymbols, filter(siblingSymbols, s => s !== indexSymbol)); // aggregate similar index infos implied to be the same key to the same combined index info - if (hasComputedStringProperty && !findIndexInfo(indexInfos, stringType)) indexInfos.push(getObjectLiteralIndexInfo(readonlyComputedStringProperty, 0, computedPropertySymbols, stringType)); - if (hasComputedNumberProperty && !findIndexInfo(indexInfos, numberType)) indexInfos.push(getObjectLiteralIndexInfo(readonlyComputedNumberProperty, 0, computedPropertySymbols, numberType)); - if (hasComputedSymbolProperty && !findIndexInfo(indexInfos, esSymbolType)) indexInfos.push(getObjectLiteralIndexInfo(readonlyComputedSymbolProperty, 0, computedPropertySymbols, esSymbolType)); + if (hasComputedStringProperty && !findIndexInfo(indexInfos, stringType)) indexInfos.push(getObjectLiteralIndexInfo(readonlyComputedStringProperty, 0, allPropertySymbols, stringType)); + if (hasComputedNumberProperty && !findIndexInfo(indexInfos, numberType)) indexInfos.push(getObjectLiteralIndexInfo(readonlyComputedNumberProperty, 0, allPropertySymbols, numberType)); + if (hasComputedSymbolProperty && !findIndexInfo(indexInfos, esSymbolType)) indexInfos.push(getObjectLiteralIndexInfo(readonlyComputedSymbolProperty, 0, allPropertySymbols, esSymbolType)); return indexInfos; } return emptyArray; @@ -50523,7 +50524,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const sym = cls.symbol; const staticInfos = getIndexInfosOfType(getTypeOfSymbol(sym)); const instanceIndexSymbol = getIndexSymbol(sym); - const instanceInfos = instanceIndexSymbol && getIndexInfosOfIndexSymbol(instanceIndexSymbol); + const instanceInfos = instanceIndexSymbol && getIndexInfosOfIndexSymbol(instanceIndexSymbol, arrayFrom(getMembersOfSymbol(sym).values())); let result; for (const infoList of [staticInfos, instanceInfos]) { if (!length(infoList)) continue; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a9852b8ed5be3..d332cf917df1e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5048,7 +5048,7 @@ export interface TypeChecker { /** @internal */ getTypeOfPropertyOfType(type: Type, propertyName: string): Type | undefined; getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined; getIndexInfosOfType(type: Type): readonly IndexInfo[]; - getIndexInfosOfIndexSymbol: (indexSymbol: Symbol) => IndexInfo[]; + getIndexInfosOfIndexSymbol: (indexSymbol: Symbol, siblingSymbols?: Symbol[] | undefined) => IndexInfo[]; getSignaturesOfType(type: Type, kind: SignatureKind): readonly Signature[]; getIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined; /** @internal */ getIndexType(type: Type): Type; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 5122694b16787..d75ab777df999 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -6119,7 +6119,7 @@ declare namespace ts { getPrivateIdentifierPropertyOfType(leftType: Type, name: string, location: Node): Symbol | undefined; getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined; getIndexInfosOfType(type: Type): readonly IndexInfo[]; - getIndexInfosOfIndexSymbol: (indexSymbol: Symbol) => IndexInfo[]; + getIndexInfosOfIndexSymbol: (indexSymbol: Symbol, siblingSymbols?: Symbol[] | undefined) => IndexInfo[]; getSignaturesOfType(type: Type, kind: SignatureKind): readonly Signature[]; getIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined; getBaseTypes(type: InterfaceType): BaseType[]; diff --git a/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt b/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt index fd58e7f478d90..90ceb463b9ce6 100644 --- a/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt +++ b/tests/baselines/reference/isolatedDeclarationErrorsClasses.errors.txt @@ -21,12 +21,11 @@ isolatedDeclarationErrorsClasses.ts(48,39): error TS7006: Parameter 'value' impl isolatedDeclarationErrorsClasses.ts(50,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. isolatedDeclarationErrorsClasses.ts(50,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. isolatedDeclarationErrorsClasses.ts(55,5): error TS1169: A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type. -isolatedDeclarationErrorsClasses.ts(56,5): error TS2411: Property '[noAnnotationLiteralName]' of type '() => any' is not assignable to 'string' index type '10'. isolatedDeclarationErrorsClasses.ts(56,5): error TS7010: '[noAnnotationLiteralName]', which lacks return-type annotation, implicitly has an 'any' return type. isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't be inferred with --isolatedDeclarations. -==== isolatedDeclarationErrorsClasses.ts (26 errors) ==== +==== isolatedDeclarationErrorsClasses.ts (25 errors) ==== export class Cls { field = 1 + 1; @@ -135,8 +134,6 @@ isolatedDeclarationErrorsClasses.ts(56,5): error TS9013: Expression type can't b !!! error TS1169: A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type. [noAnnotationLiteralName](); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property '[noAnnotationLiteralName]' of type '() => any' is not assignable to 'string' index type '10'. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS7010: '[noAnnotationLiteralName]', which lacks return-type annotation, implicitly has an 'any' return type. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS9013: Expression type can't be inferred with --isolatedDeclarations. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy