From b4024a5506253f87c61da608ed6f84ab95f7a186 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 18 Nov 2022 12:54:12 -0800 Subject: [PATCH] Preserve input key style when writing mapped type keys in declaration emit (#50781) --- src/compiler/checker.ts | 8 ++++---- ...onEmitMappedTypePropertyFromNumericStringKey.js | 14 ++++++++++++++ ...tMappedTypePropertyFromNumericStringKey.symbols | 12 ++++++++++++ ...mitMappedTypePropertyFromNumericStringKey.types | 12 ++++++++++++ ...onEmitMappedTypePropertyFromNumericStringKey.ts | 2 ++ 5 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.js create mode 100644 tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.symbols create mode 100644 tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.types create mode 100644 tests/cases/compiler/declarationEmitMappedTypePropertyFromNumericStringKey.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6007f615da6..8bb8f3869ee 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7735,23 +7735,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getPropertyNameNodeForSymbol(symbol: Symbol, context: NodeBuilderContext) { + const stringNamed = !!length(symbol.declarations) && every(symbol.declarations, isStringNamed); const singleQuote = !!length(symbol.declarations) && every(symbol.declarations, isSingleQuotedStringNamed); - const fromNameType = getPropertyNameNodeForSymbolFromNameType(symbol, context, singleQuote); + const fromNameType = getPropertyNameNodeForSymbolFromNameType(symbol, context, singleQuote, stringNamed); if (fromNameType) { return fromNameType; } const rawName = unescapeLeadingUnderscores(symbol.escapedName); - const stringNamed = !!length(symbol.declarations) && every(symbol.declarations, isStringNamed); return createPropertyNameNodeForIdentifierOrLiteral(rawName, getEmitScriptTarget(compilerOptions), singleQuote, stringNamed); } // See getNameForSymbolFromNameType for a stringy equivalent - function getPropertyNameNodeForSymbolFromNameType(symbol: Symbol, context: NodeBuilderContext, singleQuote?: boolean) { + function getPropertyNameNodeForSymbolFromNameType(symbol: Symbol, context: NodeBuilderContext, singleQuote?: boolean, stringNamed?: boolean) { const nameType = getSymbolLinks(symbol).nameType; if (nameType) { if (nameType.flags & TypeFlags.StringOrNumberLiteral) { const name = "" + (nameType as StringLiteralType | NumberLiteralType).value; - if (!isIdentifierText(name, getEmitScriptTarget(compilerOptions)) && !isNumericLiteralName(name)) { + if (!isIdentifierText(name, getEmitScriptTarget(compilerOptions)) && (stringNamed || !isNumericLiteralName(name))) { return factory.createStringLiteral(name, !!singleQuote); } if (isNumericLiteralName(name) && startsWith(name, "-")) { diff --git a/tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.js b/tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.js new file mode 100644 index 00000000000..82a79f12a59 --- /dev/null +++ b/tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.js @@ -0,0 +1,14 @@ +//// [declarationEmitMappedTypePropertyFromNumericStringKey.ts] +export const f = ((arg: {[K in keyof T]: T[K] | string}) => arg)({'0': 0}); // Original prop uses string syntax + +//// [declarationEmitMappedTypePropertyFromNumericStringKey.js] +"use strict"; +exports.__esModule = true; +exports.f = void 0; +exports.f = (function (arg) { return arg; })({ '0': 0 }); // Original prop uses string syntax + + +//// [declarationEmitMappedTypePropertyFromNumericStringKey.d.ts] +export declare const f: { + '0': string | number; +}; diff --git a/tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.symbols b/tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.symbols new file mode 100644 index 00000000000..9002d9f7339 --- /dev/null +++ b/tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.symbols @@ -0,0 +1,12 @@ +=== tests/cases/compiler/declarationEmitMappedTypePropertyFromNumericStringKey.ts === +export const f = ((arg: {[K in keyof T]: T[K] | string}) => arg)({'0': 0}); // Original prop uses string syntax +>f : Symbol(f, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 12)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 19)) +>arg : Symbol(arg, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 22)) +>K : Symbol(K, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 29)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 19)) +>T : Symbol(T, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 19)) +>K : Symbol(K, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 29)) +>arg : Symbol(arg, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 22)) +>'0' : Symbol('0', Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 69)) + diff --git a/tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.types b/tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.types new file mode 100644 index 00000000000..a039e229391 --- /dev/null +++ b/tests/baselines/reference/declarationEmitMappedTypePropertyFromNumericStringKey.types @@ -0,0 +1,12 @@ +=== tests/cases/compiler/declarationEmitMappedTypePropertyFromNumericStringKey.ts === +export const f = ((arg: {[K in keyof T]: T[K] | string}) => arg)({'0': 0}); // Original prop uses string syntax +>f : { '0': string | number; } +>((arg: {[K in keyof T]: T[K] | string}) => arg)({'0': 0}) : { '0': string | number; } +>((arg: {[K in keyof T]: T[K] | string}) => arg) : (arg: { [K in keyof T]: string | T[K]; }) => { [K in keyof T]: string | T[K]; } +>(arg: {[K in keyof T]: T[K] | string}) => arg : (arg: { [K in keyof T]: string | T[K]; }) => { [K in keyof T]: string | T[K]; } +>arg : { [K in keyof T]: string | T[K]; } +>arg : { [K in keyof T]: string | T[K]; } +>{'0': 0} : { '0': number; } +>'0' : number +>0 : 0 + diff --git a/tests/cases/compiler/declarationEmitMappedTypePropertyFromNumericStringKey.ts b/tests/cases/compiler/declarationEmitMappedTypePropertyFromNumericStringKey.ts new file mode 100644 index 00000000000..d5cfd3bac38 --- /dev/null +++ b/tests/cases/compiler/declarationEmitMappedTypePropertyFromNumericStringKey.ts @@ -0,0 +1,2 @@ +// @declaration: true +export const f = ((arg: {[K in keyof T]: T[K] | string}) => arg)({'0': 0}); // Original prop uses string syntax \ No newline at end of file