From 4609a44b7d6e028cf009418b757aebae9ecec8a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 19 Jun 2023 08:50:11 +0200 Subject: [PATCH 1/4] Do not widen computed properties with template literal types --- src/compiler/checker.ts | 45 ++- src/compiler/types.ts | 1 + ...opertyNamesTemplateLiteralTypes.errors.txt | 115 +++++++ ...mputedPropertyNamesTemplateLiteralTypes.js | 183 ++++++++++ ...dPropertyNamesTemplateLiteralTypes.symbols | 259 ++++++++++++++ ...tedPropertyNamesTemplateLiteralTypes.types | 317 ++++++++++++++++++ .../reference/indexSignatures1.types | 2 +- ...mputedPropertyNamesTemplateLiteralTypes.ts | 105 ++++++ 8 files changed, 1014 insertions(+), 13 deletions(-) create mode 100644 tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.errors.txt create mode 100644 tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.js create mode 100644 tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.symbols create mode 100644 tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.types create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNamesTemplateLiteralTypes.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 59be6353b3a86..837d1e761e6cc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -30099,18 +30099,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { isTypeAssignableToKind(checkComputedPropertyName(firstDecl.name), TypeFlags.ESSymbol)); } - function getObjectLiteralIndexInfo(node: ObjectLiteralExpression, offset: number, properties: Symbol[], keyType: Type): IndexInfo { + function getObjectLiteralIndexInfo(offset: number, properties: Symbol[], keyType: Type, isReadonly: boolean): IndexInfo { const propTypes: Type[] = []; for (let i = offset; i < properties.length; i++) { const prop = properties[i]; - if (keyType === stringType && !isSymbolWithSymbolName(prop) || - keyType === numberType && isSymbolWithNumericName(prop) || - keyType === esSymbolType && isSymbolWithSymbolName(prop)) { + if (keyType === numberType && isSymbolWithNumericName(prop) || keyType === esSymbolType && isSymbolWithSymbolName(prop)) { propTypes.push(getTypeOfSymbol(properties[i])); } + else if (!isSymbolWithSymbolName(prop)) { + if (keyType === stringType) { + propTypes.push(getTypeOfSymbol(properties[i])); + } + else { + const source = tryCast(prop, isTransientSymbol)?.links.computedNameType || getStringLiteralType(unescapeLeadingUnderscores(prop.escapedName)); + if (isTypeAssignableTo(source, keyType)) { + propTypes.push(getTypeOfSymbol(properties[i])); + } + } + } } 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 { @@ -30133,6 +30142,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const allPropertiesTable = strictNullChecks ? createSymbolTable() : undefined; let propertiesTable = createSymbolTable(); let propertiesArray: Symbol[] = []; + let computedNameTypes: Type[] = []; let spread: Type = emptyObjectType; pushCachedContextualType(node); @@ -30191,7 +30201,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (nameType) { prop.links.nameType = nameType; } - + else if (computedNameType) { + prop.links.computedNameType = computedNameType; + } if (inDestructuringPattern) { // If object literal is an assignment pattern and if the assignment pattern specifies a default value // for the property, make the property optional. @@ -30243,6 +30255,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext); propertiesArray = []; propertiesTable = createSymbolTable(); + computedNameTypes = []; hasComputedStringProperty = false; hasComputedNumberProperty = false; hasComputedSymbolProperty = false; @@ -30275,8 +30288,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkNodeDeferred(memberDecl); } - if (computedNameType && !(computedNameType.flags & TypeFlags.StringOrNumberLiteralOrUnique)) { - if (isTypeAssignableTo(computedNameType, stringNumberSymbolType)) { + if (computedNameType && !isTypeUsableAsPropertyName(computedNameType)) { + if (isPatternLiteralType(computedNameType)) { + computedNameTypes.push(computedNameType); + } + else if (isTypeAssignableTo(computedNameType, stringNumberSymbolType)) { if (isTypeAssignableTo(computedNameType, numberType)) { hasComputedNumberProperty = true; } @@ -30339,6 +30355,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext); propertiesArray = []; propertiesTable = createSymbolTable(); + computedNameTypes = []; hasComputedStringProperty = false; hasComputedNumberProperty = false; } @@ -30349,10 +30366,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return createObjectLiteralType(); 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)); + let indexInfos: IndexInfo[] = []; + for (const computedNameType of computedNameTypes) { + const indexInfo = getObjectLiteralIndexInfo(offset, propertiesArray, computedNameType, /*isReadonly*/ inConstContext); + indexInfos = appendIndexInfo(indexInfos, indexInfo, /*union*/ true); + } + if (hasComputedStringProperty) indexInfos.push(getObjectLiteralIndexInfo(offset, propertiesArray, stringType, /*isReadonly*/ inConstContext)); + if (hasComputedNumberProperty) indexInfos.push(getObjectLiteralIndexInfo(offset, propertiesArray, numberType, /*isReadonly*/ inConstContext)); + if (hasComputedSymbolProperty) indexInfos.push(getObjectLiteralIndexInfo(offset, propertiesArray, esSymbolType, /*isReadonly*/ inConstContext)); const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, indexInfos); result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral; if (isJSObjectLiteral) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 008d4d710bea5..489b6e8992aca 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5839,6 +5839,7 @@ export interface SymbolLinks { type?: Type; // Type of value symbol writeType?: Type; // Type of value symbol in write contexts nameType?: Type; // Type associated with a late-bound symbol + computedNameType?: Type; // Type of the computed property name not usable as property name uniqueESSymbolType?: Type; // UniqueESSymbol type for a symbol declaredType?: Type; // Type of class, interface, enum, type alias, or type parameter typeParameters?: TypeParameter[]; // Type parameters of type alias (undefined if non-generic) diff --git a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.errors.txt b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.errors.txt new file mode 100644 index 0000000000000..f879a32417fa9 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.errors.txt @@ -0,0 +1,115 @@ +computedPropertyNamesTemplateLiteralTypes.ts(94,7): error TS2322: Type '{ [x: string]: string | number[]; name: string; }' is not assignable to type 'IDocument_46309'. + 'string' and '`added_${string}`' index signatures are incompatible. + Type 'string | number[]' is not assignable to type 'number[] | undefined'. + Type 'string' is not assignable to type 'number[]'. + + +==== computedPropertyNamesTemplateLiteralTypes.ts (1 errors) ==== + declare const str1: string; + declare const pattern1: `foo${string}`; + declare const pattern2: `foobar${string}`; + declare const samepattern1: `foo${string}`; + + const obj1 = { + [pattern1]: true, + }; + + const obj2 = { + [pattern1]: true, + [str1]: 100, + }; + + const obj3 = { + [str1]: 100, + [pattern1]: true, + }; + + const obj4 = { + [pattern1]: true, + [pattern2]: "hello", + }; + + const obj5 = { + [pattern2]: "hello", + [pattern1]: true, + }; + + const obj6 = { + [pattern1]: true, + [pattern2]: "hello", + other: 100, + }; + + const obj7 = { + [pattern1]: true, + [pattern2]: "hello", + fooooooooo: 100, + }; + + const obj8 = { + [pattern1]: true, + [pattern2]: "hello", + foobarrrrr: 100, + }; + + const obj9 = { + [pattern1]: true, + [samepattern1]: "hello", + }; + + const obj10 = { + [pattern1]: true, + } as const; + + const obj11 = { + [pattern1]: 100, + ...obj9, + }; + + const obj12 = { + ...obj9, + [pattern1]: 100, + }; + + const obj13 = { + [pattern1]: 100, + ...{ + [pattern2]: "hello", + }, + }; + + const obj14 = { + [pattern1]: 100, + ...{ + [pattern1]: true, + [pattern2]: "hello", + foobarrrrr: [1, 2, 3], + }, + }; + + // repro from https://github.com/microsoft/TypeScript/issues/46309 + + interface IDocument_46309 { + name: string; + [added_: `added_${string}`]: number[] | undefined; + } + + const tech1_46309 = { + uuid: "70b26275-5096-4e4b-9d50-3c965c9e5073", + }; + + const doc_46309: IDocument_46309 = { + ~~~~~~~~~ +!!! error TS2322: Type '{ [x: string]: string | number[]; name: string; }' is not assignable to type 'IDocument_46309'. +!!! error TS2322: 'string' and '`added_${string}`' index signatures are incompatible. +!!! error TS2322: Type 'string | number[]' is not assignable to type 'number[] | undefined'. +!!! error TS2322: Type 'string' is not assignable to type 'number[]'. + name: "", + [`added_${tech1_46309.uuid}`]: [19700101], + }; + + const doc2_46309: IDocument_46309 = { + name: "", + [`added_${tech1_46309.uuid}` as const]: [19700101], + }; + \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.js b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.js new file mode 100644 index 0000000000000..1cde62e0f403f --- /dev/null +++ b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.js @@ -0,0 +1,183 @@ +//// [tests/cases/conformance/es6/computedProperties/computedPropertyNamesTemplateLiteralTypes.ts] //// + +//// [computedPropertyNamesTemplateLiteralTypes.ts] +declare const str1: string; +declare const pattern1: `foo${string}`; +declare const pattern2: `foobar${string}`; +declare const samepattern1: `foo${string}`; + +const obj1 = { + [pattern1]: true, +}; + +const obj2 = { + [pattern1]: true, + [str1]: 100, +}; + +const obj3 = { + [str1]: 100, + [pattern1]: true, +}; + +const obj4 = { + [pattern1]: true, + [pattern2]: "hello", +}; + +const obj5 = { + [pattern2]: "hello", + [pattern1]: true, +}; + +const obj6 = { + [pattern1]: true, + [pattern2]: "hello", + other: 100, +}; + +const obj7 = { + [pattern1]: true, + [pattern2]: "hello", + fooooooooo: 100, +}; + +const obj8 = { + [pattern1]: true, + [pattern2]: "hello", + foobarrrrr: 100, +}; + +const obj9 = { + [pattern1]: true, + [samepattern1]: "hello", +}; + +const obj10 = { + [pattern1]: true, +} as const; + +const obj11 = { + [pattern1]: 100, + ...obj9, +}; + +const obj12 = { + ...obj9, + [pattern1]: 100, +}; + +const obj13 = { + [pattern1]: 100, + ...{ + [pattern2]: "hello", + }, +}; + +const obj14 = { + [pattern1]: 100, + ...{ + [pattern1]: true, + [pattern2]: "hello", + foobarrrrr: [1, 2, 3], + }, +}; + +// repro from https://github.com/microsoft/TypeScript/issues/46309 + +interface IDocument_46309 { + name: string; + [added_: `added_${string}`]: number[] | undefined; +} + +const tech1_46309 = { + uuid: "70b26275-5096-4e4b-9d50-3c965c9e5073", +}; + +const doc_46309: IDocument_46309 = { + name: "", + [`added_${tech1_46309.uuid}`]: [19700101], +}; + +const doc2_46309: IDocument_46309 = { + name: "", + [`added_${tech1_46309.uuid}` as const]: [19700101], +}; + + +//// [computedPropertyNamesTemplateLiteralTypes.js] +"use strict"; +const obj1 = { + [pattern1]: true, +}; +const obj2 = { + [pattern1]: true, + [str1]: 100, +}; +const obj3 = { + [str1]: 100, + [pattern1]: true, +}; +const obj4 = { + [pattern1]: true, + [pattern2]: "hello", +}; +const obj5 = { + [pattern2]: "hello", + [pattern1]: true, +}; +const obj6 = { + [pattern1]: true, + [pattern2]: "hello", + other: 100, +}; +const obj7 = { + [pattern1]: true, + [pattern2]: "hello", + fooooooooo: 100, +}; +const obj8 = { + [pattern1]: true, + [pattern2]: "hello", + foobarrrrr: 100, +}; +const obj9 = { + [pattern1]: true, + [samepattern1]: "hello", +}; +const obj10 = { + [pattern1]: true, +}; +const obj11 = { + [pattern1]: 100, + ...obj9, +}; +const obj12 = { + ...obj9, + [pattern1]: 100, +}; +const obj13 = { + [pattern1]: 100, + ...{ + [pattern2]: "hello", + }, +}; +const obj14 = { + [pattern1]: 100, + ...{ + [pattern1]: true, + [pattern2]: "hello", + foobarrrrr: [1, 2, 3], + }, +}; +const tech1_46309 = { + uuid: "70b26275-5096-4e4b-9d50-3c965c9e5073", +}; +const doc_46309 = { + name: "", + [`added_${tech1_46309.uuid}`]: [19700101], +}; +const doc2_46309 = { + name: "", + [`added_${tech1_46309.uuid}`]: [19700101], +}; diff --git a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.symbols b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.symbols new file mode 100644 index 0000000000000..d34f12fbe3f0c --- /dev/null +++ b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.symbols @@ -0,0 +1,259 @@ +//// [tests/cases/conformance/es6/computedProperties/computedPropertyNamesTemplateLiteralTypes.ts] //// + +=== computedPropertyNamesTemplateLiteralTypes.ts === +declare const str1: string; +>str1 : Symbol(str1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 0, 13)) + +declare const pattern1: `foo${string}`; +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + +declare const pattern2: `foobar${string}`; +>pattern2 : Symbol(pattern2, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 2, 13)) + +declare const samepattern1: `foo${string}`; +>samepattern1 : Symbol(samepattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 3, 13)) + +const obj1 = { +>obj1 : Symbol(obj1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 5, 5)) + + [pattern1]: true, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 5, 14)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + +}; + +const obj2 = { +>obj2 : Symbol(obj2, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 9, 5)) + + [pattern1]: true, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 9, 14)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + + [str1]: 100, +>[str1] : Symbol([str1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 10, 19)) +>str1 : Symbol(str1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 0, 13)) + +}; + +const obj3 = { +>obj3 : Symbol(obj3, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 14, 5)) + + [str1]: 100, +>[str1] : Symbol([str1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 14, 14)) +>str1 : Symbol(str1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 0, 13)) + + [pattern1]: true, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 15, 14)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + +}; + +const obj4 = { +>obj4 : Symbol(obj4, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 19, 5)) + + [pattern1]: true, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 19, 14)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + + [pattern2]: "hello", +>[pattern2] : Symbol([pattern2], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 20, 19)) +>pattern2 : Symbol(pattern2, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 2, 13)) + +}; + +const obj5 = { +>obj5 : Symbol(obj5, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 24, 5)) + + [pattern2]: "hello", +>[pattern2] : Symbol([pattern2], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 24, 14)) +>pattern2 : Symbol(pattern2, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 2, 13)) + + [pattern1]: true, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 25, 22)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + +}; + +const obj6 = { +>obj6 : Symbol(obj6, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 29, 5)) + + [pattern1]: true, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 29, 14)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + + [pattern2]: "hello", +>[pattern2] : Symbol([pattern2], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 30, 19)) +>pattern2 : Symbol(pattern2, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 2, 13)) + + other: 100, +>other : Symbol(other, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 31, 22)) + +}; + +const obj7 = { +>obj7 : Symbol(obj7, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 35, 5)) + + [pattern1]: true, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 35, 14)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + + [pattern2]: "hello", +>[pattern2] : Symbol([pattern2], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 36, 19)) +>pattern2 : Symbol(pattern2, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 2, 13)) + + fooooooooo: 100, +>fooooooooo : Symbol(fooooooooo, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 37, 22)) + +}; + +const obj8 = { +>obj8 : Symbol(obj8, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 41, 5)) + + [pattern1]: true, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 41, 14)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + + [pattern2]: "hello", +>[pattern2] : Symbol([pattern2], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 42, 19)) +>pattern2 : Symbol(pattern2, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 2, 13)) + + foobarrrrr: 100, +>foobarrrrr : Symbol(foobarrrrr, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 43, 22)) + +}; + +const obj9 = { +>obj9 : Symbol(obj9, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 47, 5)) + + [pattern1]: true, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 47, 14)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + + [samepattern1]: "hello", +>[samepattern1] : Symbol([samepattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 48, 19)) +>samepattern1 : Symbol(samepattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 3, 13)) + +}; + +const obj10 = { +>obj10 : Symbol(obj10, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 52, 5)) + + [pattern1]: true, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 52, 15)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + +} as const; +>const : Symbol(const) + +const obj11 = { +>obj11 : Symbol(obj11, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 56, 5)) + + [pattern1]: 100, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 56, 15)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + + ...obj9, +>obj9 : Symbol(obj9, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 47, 5)) + +}; + +const obj12 = { +>obj12 : Symbol(obj12, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 61, 5)) + + ...obj9, +>obj9 : Symbol(obj9, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 47, 5)) + + [pattern1]: 100, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 62, 10)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + +}; + +const obj13 = { +>obj13 : Symbol(obj13, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 66, 5)) + + [pattern1]: 100, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 66, 15)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + + ...{ + [pattern2]: "hello", +>[pattern2] : Symbol([pattern2], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 68, 6)) +>pattern2 : Symbol(pattern2, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 2, 13)) + + }, +}; + +const obj14 = { +>obj14 : Symbol(obj14, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 73, 5)) + + [pattern1]: 100, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 73, 15)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + + ...{ + [pattern1]: true, +>[pattern1] : Symbol([pattern1], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 75, 6)) +>pattern1 : Symbol(pattern1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 1, 13)) + + [pattern2]: "hello", +>[pattern2] : Symbol([pattern2], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 76, 21)) +>pattern2 : Symbol(pattern2, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 2, 13)) + + foobarrrrr: [1, 2, 3], +>foobarrrrr : Symbol(foobarrrrr, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 77, 24)) + + }, +}; + +// repro from https://github.com/microsoft/TypeScript/issues/46309 + +interface IDocument_46309 { +>IDocument_46309 : Symbol(IDocument_46309, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 80, 2)) + + name: string; +>name : Symbol(IDocument_46309.name, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 84, 27)) + + [added_: `added_${string}`]: number[] | undefined; +>added_ : Symbol(added_, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 86, 3)) +} + +const tech1_46309 = { +>tech1_46309 : Symbol(tech1_46309, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 89, 5)) + + uuid: "70b26275-5096-4e4b-9d50-3c965c9e5073", +>uuid : Symbol(uuid, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 89, 21)) + +}; + +const doc_46309: IDocument_46309 = { +>doc_46309 : Symbol(doc_46309, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 93, 5)) +>IDocument_46309 : Symbol(IDocument_46309, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 80, 2)) + + name: "", +>name : Symbol(name, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 93, 36)) + + [`added_${tech1_46309.uuid}`]: [19700101], +>[`added_${tech1_46309.uuid}`] : Symbol([`added_${tech1_46309.uuid}`], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 94, 11)) +>tech1_46309.uuid : Symbol(uuid, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 89, 21)) +>tech1_46309 : Symbol(tech1_46309, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 89, 5)) +>uuid : Symbol(uuid, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 89, 21)) + +}; + +const doc2_46309: IDocument_46309 = { +>doc2_46309 : Symbol(doc2_46309, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 98, 5)) +>IDocument_46309 : Symbol(IDocument_46309, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 80, 2)) + + name: "", +>name : Symbol(name, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 98, 37)) + + [`added_${tech1_46309.uuid}` as const]: [19700101], +>[`added_${tech1_46309.uuid}` as const] : Symbol([`added_${tech1_46309.uuid}` as const], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 99, 11)) +>tech1_46309.uuid : Symbol(uuid, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 89, 21)) +>tech1_46309 : Symbol(tech1_46309, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 89, 5)) +>uuid : Symbol(uuid, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 89, 21)) +>const : Symbol(const) + +}; + diff --git a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.types b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.types new file mode 100644 index 0000000000000..03fb8dd278d69 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.types @@ -0,0 +1,317 @@ +//// [tests/cases/conformance/es6/computedProperties/computedPropertyNamesTemplateLiteralTypes.ts] //// + +=== computedPropertyNamesTemplateLiteralTypes.ts === +declare const str1: string; +>str1 : string + +declare const pattern1: `foo${string}`; +>pattern1 : `foo${string}` + +declare const pattern2: `foobar${string}`; +>pattern2 : `foobar${string}` + +declare const samepattern1: `foo${string}`; +>samepattern1 : `foo${string}` + +const obj1 = { +>obj1 : { [x: `foo${string}`]: boolean; } +>{ [pattern1]: true,} : { [x: `foo${string}`]: boolean; } + + [pattern1]: true, +>[pattern1] : boolean +>pattern1 : `foo${string}` +>true : true + +}; + +const obj2 = { +>obj2 : { [x: `foo${string}`]: boolean; [x: string]: number | boolean; } +>{ [pattern1]: true, [str1]: 100,} : { [x: `foo${string}`]: boolean; [x: string]: number | boolean; } + + [pattern1]: true, +>[pattern1] : boolean +>pattern1 : `foo${string}` +>true : true + + [str1]: 100, +>[str1] : number +>str1 : string +>100 : 100 + +}; + +const obj3 = { +>obj3 : { [x: string]: number | boolean; [x: `foo${string}`]: boolean; } +>{ [str1]: 100, [pattern1]: true,} : { [x: string]: number | boolean; [x: `foo${string}`]: boolean; } + + [str1]: 100, +>[str1] : number +>str1 : string +>100 : 100 + + [pattern1]: true, +>[pattern1] : boolean +>pattern1 : `foo${string}` +>true : true + +}; + +const obj4 = { +>obj4 : { [x: `foo${string}`]: string | boolean; [x: `foobar${string}`]: string; } +>{ [pattern1]: true, [pattern2]: "hello",} : { [x: `foo${string}`]: string | boolean; [x: `foobar${string}`]: string; } + + [pattern1]: true, +>[pattern1] : boolean +>pattern1 : `foo${string}` +>true : true + + [pattern2]: "hello", +>[pattern2] : string +>pattern2 : `foobar${string}` +>"hello" : "hello" + +}; + +const obj5 = { +>obj5 : { [x: `foobar${string}`]: string; [x: `foo${string}`]: string | boolean; } +>{ [pattern2]: "hello", [pattern1]: true,} : { [x: `foobar${string}`]: string; [x: `foo${string}`]: string | boolean; } + + [pattern2]: "hello", +>[pattern2] : string +>pattern2 : `foobar${string}` +>"hello" : "hello" + + [pattern1]: true, +>[pattern1] : boolean +>pattern1 : `foo${string}` +>true : true + +}; + +const obj6 = { +>obj6 : { [x: `foo${string}`]: string | boolean; [x: `foobar${string}`]: string; other: number; } +>{ [pattern1]: true, [pattern2]: "hello", other: 100,} : { [x: `foo${string}`]: string | boolean; [x: `foobar${string}`]: string; other: number; } + + [pattern1]: true, +>[pattern1] : boolean +>pattern1 : `foo${string}` +>true : true + + [pattern2]: "hello", +>[pattern2] : string +>pattern2 : `foobar${string}` +>"hello" : "hello" + + other: 100, +>other : number +>100 : 100 + +}; + +const obj7 = { +>obj7 : { [x: `foo${string}`]: string | number | boolean; [x: `foobar${string}`]: string; fooooooooo: number; } +>{ [pattern1]: true, [pattern2]: "hello", fooooooooo: 100,} : { [x: `foo${string}`]: string | number | boolean; [x: `foobar${string}`]: string; fooooooooo: number; } + + [pattern1]: true, +>[pattern1] : boolean +>pattern1 : `foo${string}` +>true : true + + [pattern2]: "hello", +>[pattern2] : string +>pattern2 : `foobar${string}` +>"hello" : "hello" + + fooooooooo: 100, +>fooooooooo : number +>100 : 100 + +}; + +const obj8 = { +>obj8 : { [x: `foo${string}`]: string | number | boolean; [x: `foobar${string}`]: string | number; foobarrrrr: number; } +>{ [pattern1]: true, [pattern2]: "hello", foobarrrrr: 100,} : { [x: `foo${string}`]: string | number | boolean; [x: `foobar${string}`]: string | number; foobarrrrr: number; } + + [pattern1]: true, +>[pattern1] : boolean +>pattern1 : `foo${string}` +>true : true + + [pattern2]: "hello", +>[pattern2] : string +>pattern2 : `foobar${string}` +>"hello" : "hello" + + foobarrrrr: 100, +>foobarrrrr : number +>100 : 100 + +}; + +const obj9 = { +>obj9 : { [x: `foo${string}`]: string | boolean; } +>{ [pattern1]: true, [samepattern1]: "hello",} : { [x: `foo${string}`]: string | boolean; } + + [pattern1]: true, +>[pattern1] : boolean +>pattern1 : `foo${string}` +>true : true + + [samepattern1]: "hello", +>[samepattern1] : string +>samepattern1 : `foo${string}` +>"hello" : "hello" + +}; + +const obj10 = { +>obj10 : { readonly [x: `foo${string}`]: true; } +>{ [pattern1]: true,} as const : { readonly [x: `foo${string}`]: true; } +>{ [pattern1]: true,} : { readonly [x: `foo${string}`]: true; } + + [pattern1]: true, +>[pattern1] : true +>pattern1 : `foo${string}` +>true : true + +} as const; + +const obj11 = { +>obj11 : { [x: `foo${string}`]: string | number | boolean; } +>{ [pattern1]: 100, ...obj9,} : { [x: `foo${string}`]: string | number | boolean; } + + [pattern1]: 100, +>[pattern1] : number +>pattern1 : `foo${string}` +>100 : 100 + + ...obj9, +>obj9 : { [x: `foo${string}`]: string | boolean; } + +}; + +const obj12 = { +>obj12 : { [x: `foo${string}`]: string | number | boolean; } +>{ ...obj9, [pattern1]: 100,} : { [x: `foo${string}`]: string | number | boolean; } + + ...obj9, +>obj9 : { [x: `foo${string}`]: string | boolean; } + + [pattern1]: 100, +>[pattern1] : number +>pattern1 : `foo${string}` +>100 : 100 + +}; + +const obj13 = { +>obj13 : {} +>{ [pattern1]: 100, ...{ [pattern2]: "hello", },} : {} + + [pattern1]: 100, +>[pattern1] : number +>pattern1 : `foo${string}` +>100 : 100 + + ...{ +>{ [pattern2]: "hello", } : { [x: `foobar${string}`]: string; } + + [pattern2]: "hello", +>[pattern2] : string +>pattern2 : `foobar${string}` +>"hello" : "hello" + + }, +}; + +const obj14 = { +>obj14 : { [x: `foo${string}`]: string | number | boolean | number[]; foobarrrrr: number[]; } +>{ [pattern1]: 100, ...{ [pattern1]: true, [pattern2]: "hello", foobarrrrr: [1, 2, 3], },} : { [x: `foo${string}`]: string | number | boolean | number[]; foobarrrrr: number[]; } + + [pattern1]: 100, +>[pattern1] : number +>pattern1 : `foo${string}` +>100 : 100 + + ...{ +>{ [pattern1]: true, [pattern2]: "hello", foobarrrrr: [1, 2, 3], } : { [x: `foo${string}`]: string | boolean | number[]; [x: `foobar${string}`]: string | number[]; foobarrrrr: number[]; } + + [pattern1]: true, +>[pattern1] : boolean +>pattern1 : `foo${string}` +>true : true + + [pattern2]: "hello", +>[pattern2] : string +>pattern2 : `foobar${string}` +>"hello" : "hello" + + foobarrrrr: [1, 2, 3], +>foobarrrrr : number[] +>[1, 2, 3] : number[] +>1 : 1 +>2 : 2 +>3 : 3 + + }, +}; + +// repro from https://github.com/microsoft/TypeScript/issues/46309 + +interface IDocument_46309 { + name: string; +>name : string + + [added_: `added_${string}`]: number[] | undefined; +>added_ : `added_${string}` +} + +const tech1_46309 = { +>tech1_46309 : { uuid: string; } +>{ uuid: "70b26275-5096-4e4b-9d50-3c965c9e5073",} : { uuid: string; } + + uuid: "70b26275-5096-4e4b-9d50-3c965c9e5073", +>uuid : string +>"70b26275-5096-4e4b-9d50-3c965c9e5073" : "70b26275-5096-4e4b-9d50-3c965c9e5073" + +}; + +const doc_46309: IDocument_46309 = { +>doc_46309 : IDocument_46309 +>{ name: "", [`added_${tech1_46309.uuid}`]: [19700101],} : { [x: string]: string | number[]; name: string; } + + name: "", +>name : string +>"" : "" + + [`added_${tech1_46309.uuid}`]: [19700101], +>[`added_${tech1_46309.uuid}`] : number[] +>`added_${tech1_46309.uuid}` : string +>tech1_46309.uuid : string +>tech1_46309 : { uuid: string; } +>uuid : string +>[19700101] : number[] +>19700101 : 19700101 + +}; + +const doc2_46309: IDocument_46309 = { +>doc2_46309 : IDocument_46309 +>{ name: "", [`added_${tech1_46309.uuid}` as const]: [19700101],} : { [x: `added_${string}`]: number[]; name: string; } + + name: "", +>name : string +>"" : "" + + [`added_${tech1_46309.uuid}` as const]: [19700101], +>[`added_${tech1_46309.uuid}` as const] : number[] +>`added_${tech1_46309.uuid}` as const : `added_${string}` +>`added_${tech1_46309.uuid}` : `added_${string}` +>tech1_46309.uuid : string +>tech1_46309 : { uuid: string; } +>uuid : string +>[19700101] : number[] +>19700101 : 19700101 + +}; + diff --git a/tests/baselines/reference/indexSignatures1.types b/tests/baselines/reference/indexSignatures1.types index 4f7e248192fb8..329cbab7c73dd 100644 --- a/tests/baselines/reference/indexSignatures1.types +++ b/tests/baselines/reference/indexSignatures1.types @@ -998,7 +998,7 @@ type A = Record; const a: A = { [id]: 'test' } >a : A ->{ [id]: 'test' } : { [x: string]: string; } +>{ [id]: 'test' } : { [x: `${number}-${number}-${number}-${number}`]: string; } >[id] : string >id : `${number}-${number}-${number}-${number}` >'test' : "test" diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNamesTemplateLiteralTypes.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNamesTemplateLiteralTypes.ts new file mode 100644 index 0000000000000..22772028135c3 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNamesTemplateLiteralTypes.ts @@ -0,0 +1,105 @@ +// @strict: true +// @target: esnext + +declare const str1: string; +declare const pattern1: `foo${string}`; +declare const pattern2: `foobar${string}`; +declare const samepattern1: `foo${string}`; + +const obj1 = { + [pattern1]: true, +}; + +const obj2 = { + [pattern1]: true, + [str1]: 100, +}; + +const obj3 = { + [str1]: 100, + [pattern1]: true, +}; + +const obj4 = { + [pattern1]: true, + [pattern2]: "hello", +}; + +const obj5 = { + [pattern2]: "hello", + [pattern1]: true, +}; + +const obj6 = { + [pattern1]: true, + [pattern2]: "hello", + other: 100, +}; + +const obj7 = { + [pattern1]: true, + [pattern2]: "hello", + fooooooooo: 100, +}; + +const obj8 = { + [pattern1]: true, + [pattern2]: "hello", + foobarrrrr: 100, +}; + +const obj9 = { + [pattern1]: true, + [samepattern1]: "hello", +}; + +const obj10 = { + [pattern1]: true, +} as const; + +const obj11 = { + [pattern1]: 100, + ...obj9, +}; + +const obj12 = { + ...obj9, + [pattern1]: 100, +}; + +const obj13 = { + [pattern1]: 100, + ...{ + [pattern2]: "hello", + }, +}; + +const obj14 = { + [pattern1]: 100, + ...{ + [pattern1]: true, + [pattern2]: "hello", + foobarrrrr: [1, 2, 3], + }, +}; + +// repro from https://github.com/microsoft/TypeScript/issues/46309 + +interface IDocument_46309 { + name: string; + [added_: `added_${string}`]: number[] | undefined; +} + +const tech1_46309 = { + uuid: "70b26275-5096-4e4b-9d50-3c965c9e5073", +}; + +const doc_46309: IDocument_46309 = { + name: "", + [`added_${tech1_46309.uuid}`]: [19700101], +}; + +const doc2_46309: IDocument_46309 = { + name: "", + [`added_${tech1_46309.uuid}` as const]: [19700101], +}; From 275410d4ba787687df9ab310585fff919eaba74e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 19 Jun 2023 17:09:39 +0200 Subject: [PATCH 2/4] Simplify the implementation by using a `Set` --- src/compiler/checker.ts | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 837d1e761e6cc..a20960371b808 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -30142,7 +30142,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const allPropertiesTable = strictNullChecks ? createSymbolTable() : undefined; let propertiesTable = createSymbolTable(); let propertiesArray: Symbol[] = []; - let computedNameTypes: Type[] = []; + let indexKeyTypes = new Set(); let spread: Type = emptyObjectType; pushCachedContextualType(node); @@ -30156,9 +30156,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const isJSObjectLiteral = !contextualType && isInJavascript && !enumTag; let objectFlags: ObjectFlags = freshObjectLiteralFlag; let patternWithComputedProperties = false; - let hasComputedStringProperty = false; - let hasComputedNumberProperty = false; - let hasComputedSymbolProperty = false; // Spreads may cause an early bail; ensure computed names are always checked (this is cached) // As otherwise they may not be checked until exports for the type at this position are retrieved, @@ -30255,10 +30252,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext); propertiesArray = []; propertiesTable = createSymbolTable(); - computedNameTypes = []; - hasComputedStringProperty = false; - hasComputedNumberProperty = false; - hasComputedSymbolProperty = false; + indexKeyTypes = new Set(); } const type = getReducedType(checkExpression(memberDecl.expression, checkMode & CheckMode.Inferential)); if (isValidSpreadType(type)) { @@ -30290,17 +30284,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (computedNameType && !isTypeUsableAsPropertyName(computedNameType)) { if (isPatternLiteralType(computedNameType)) { - computedNameTypes.push(computedNameType); + indexKeyTypes.add(computedNameType); } else if (isTypeAssignableTo(computedNameType, stringNumberSymbolType)) { if (isTypeAssignableTo(computedNameType, numberType)) { - hasComputedNumberProperty = true; + indexKeyTypes.add(numberType); } else if (isTypeAssignableTo(computedNameType, esSymbolType)) { - hasComputedSymbolProperty = true; + indexKeyTypes.add(esSymbolType); } else { - hasComputedStringProperty = true; + indexKeyTypes.add(stringType); } if (inDestructuringPattern) { patternWithComputedProperties = true; @@ -30355,9 +30349,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext); propertiesArray = []; propertiesTable = createSymbolTable(); - computedNameTypes = []; - hasComputedStringProperty = false; - hasComputedNumberProperty = false; + indexKeyTypes = new Set(); } // remap the raw emptyObjectType fed in at the top into a fresh empty object literal type, unique to this use site return mapType(spread, t => t === emptyObjectType ? createObjectLiteralType() : t); @@ -30366,14 +30358,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return createObjectLiteralType(); function createObjectLiteralType() { - let indexInfos: IndexInfo[] = []; - for (const computedNameType of computedNameTypes) { - const indexInfo = getObjectLiteralIndexInfo(offset, propertiesArray, computedNameType, /*isReadonly*/ inConstContext); - indexInfos = appendIndexInfo(indexInfos, indexInfo, /*union*/ true); + const indexInfos: IndexInfo[] = []; + for (const keyType of indexKeyTypes) { + indexInfos.push(getObjectLiteralIndexInfo(offset, propertiesArray, keyType, /*isReadonly*/ inConstContext)); } - if (hasComputedStringProperty) indexInfos.push(getObjectLiteralIndexInfo(offset, propertiesArray, stringType, /*isReadonly*/ inConstContext)); - if (hasComputedNumberProperty) indexInfos.push(getObjectLiteralIndexInfo(offset, propertiesArray, numberType, /*isReadonly*/ inConstContext)); - if (hasComputedSymbolProperty) indexInfos.push(getObjectLiteralIndexInfo(offset, propertiesArray, esSymbolType, /*isReadonly*/ inConstContext)); const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, indexInfos); result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral; if (isJSObjectLiteral) { From 6e0b73378de4ee5ac1bc121ee0252583704217ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 19 Jun 2023 18:28:05 +0200 Subject: [PATCH 3/4] Just use `getSymbolLinks` --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a20960371b808..2d06887ee5e69 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -30111,7 +30111,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { propTypes.push(getTypeOfSymbol(properties[i])); } else { - const source = tryCast(prop, isTransientSymbol)?.links.computedNameType || getStringLiteralType(unescapeLeadingUnderscores(prop.escapedName)); + const source = getSymbolLinks(prop).computedNameType || getStringLiteralType(unescapeLeadingUnderscores(prop.escapedName)); if (isTypeAssignableTo(source, keyType)) { propTypes.push(getTypeOfSymbol(properties[i])); } From 47cb3077c6937e6407292760c35369ad20af5e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 11 Nov 2023 17:42:02 +0100 Subject: [PATCH 4/4] add a basic generic test case --- ...opertyNamesTemplateLiteralTypes.errors.txt | 7 +++++++ ...mputedPropertyNamesTemplateLiteralTypes.js | 13 ++++++++++++ ...dPropertyNamesTemplateLiteralTypes.symbols | 19 +++++++++++++++++ ...tedPropertyNamesTemplateLiteralTypes.types | 21 +++++++++++++++++++ ...mputedPropertyNamesTemplateLiteralTypes.ts | 7 +++++++ 5 files changed, 67 insertions(+) diff --git a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.errors.txt b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.errors.txt index f879a32417fa9..5d8cec76fe3ba 100644 --- a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.errors.txt +++ b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.errors.txt @@ -112,4 +112,11 @@ computedPropertyNamesTemplateLiteralTypes.ts(94,7): error TS2322: Type '{ [x: st name: "", [`added_${tech1_46309.uuid}` as const]: [19700101], }; + + function genericFn1(input: T) { + const genericPattern = `get${input}` as const; + return { + [genericPattern]: 1, + }; + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.js b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.js index 1cde62e0f403f..0b3d9c7a8906d 100644 --- a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.js +++ b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.js @@ -103,6 +103,13 @@ const doc2_46309: IDocument_46309 = { name: "", [`added_${tech1_46309.uuid}` as const]: [19700101], }; + +function genericFn1(input: T) { + const genericPattern = `get${input}` as const; + return { + [genericPattern]: 1, + }; +} //// [computedPropertyNamesTemplateLiteralTypes.js] @@ -181,3 +188,9 @@ const doc2_46309 = { name: "", [`added_${tech1_46309.uuid}`]: [19700101], }; +function genericFn1(input) { + const genericPattern = `get${input}`; + return { + [genericPattern]: 1, + }; +} diff --git a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.symbols b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.symbols index d34f12fbe3f0c..eb477f6a06739 100644 --- a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.symbols +++ b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.symbols @@ -257,3 +257,22 @@ const doc2_46309: IDocument_46309 = { }; +function genericFn1(input: T) { +>genericFn1 : Symbol(genericFn1, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 101, 2)) +>T : Symbol(T, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 103, 20)) +>input : Symbol(input, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 103, 38)) +>T : Symbol(T, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 103, 20)) + + const genericPattern = `get${input}` as const; +>genericPattern : Symbol(genericPattern, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 104, 7)) +>input : Symbol(input, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 103, 38)) +>const : Symbol(const) + + return { + [genericPattern]: 1, +>[genericPattern] : Symbol([genericPattern], Decl(computedPropertyNamesTemplateLiteralTypes.ts, 105, 10)) +>genericPattern : Symbol(genericPattern, Decl(computedPropertyNamesTemplateLiteralTypes.ts, 104, 7)) + + }; +} + diff --git a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.types b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.types index 03fb8dd278d69..bbcd73be837b0 100644 --- a/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.types +++ b/tests/baselines/reference/computedPropertyNamesTemplateLiteralTypes.types @@ -315,3 +315,24 @@ const doc2_46309: IDocument_46309 = { }; +function genericFn1(input: T) { +>genericFn1 : (input: T) => { [x: string]: number; } +>input : T + + const genericPattern = `get${input}` as const; +>genericPattern : `get${T}` +>`get${input}` as const : `get${T}` +>`get${input}` : `get${T}` +>input : T + + return { +>{ [genericPattern]: 1, } : { [x: string]: number; } + + [genericPattern]: 1, +>[genericPattern] : number +>genericPattern : `get${T}` +>1 : 1 + + }; +} + diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNamesTemplateLiteralTypes.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNamesTemplateLiteralTypes.ts index 22772028135c3..271239665a24b 100644 --- a/tests/cases/conformance/es6/computedProperties/computedPropertyNamesTemplateLiteralTypes.ts +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNamesTemplateLiteralTypes.ts @@ -103,3 +103,10 @@ const doc2_46309: IDocument_46309 = { name: "", [`added_${tech1_46309.uuid}` as const]: [19700101], }; + +function genericFn1(input: T) { + const genericPattern = `get${input}` as const; + return { + [genericPattern]: 1, + }; +}