Skip to content

Commit b4024a5

Browse files
authored
Preserve input key style when writing mapped type keys in declaration emit (microsoft#50781)
1 parent 89d9af2 commit b4024a5

5 files changed

+44
-4
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7735,23 +7735,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
77357735
}
77367736

77377737
function getPropertyNameNodeForSymbol(symbol: Symbol, context: NodeBuilderContext) {
7738+
const stringNamed = !!length(symbol.declarations) && every(symbol.declarations, isStringNamed);
77387739
const singleQuote = !!length(symbol.declarations) && every(symbol.declarations, isSingleQuotedStringNamed);
7739-
const fromNameType = getPropertyNameNodeForSymbolFromNameType(symbol, context, singleQuote);
7740+
const fromNameType = getPropertyNameNodeForSymbolFromNameType(symbol, context, singleQuote, stringNamed);
77407741
if (fromNameType) {
77417742
return fromNameType;
77427743
}
77437744
const rawName = unescapeLeadingUnderscores(symbol.escapedName);
7744-
const stringNamed = !!length(symbol.declarations) && every(symbol.declarations, isStringNamed);
77457745
return createPropertyNameNodeForIdentifierOrLiteral(rawName, getEmitScriptTarget(compilerOptions), singleQuote, stringNamed);
77467746
}
77477747

77487748
// See getNameForSymbolFromNameType for a stringy equivalent
7749-
function getPropertyNameNodeForSymbolFromNameType(symbol: Symbol, context: NodeBuilderContext, singleQuote?: boolean) {
7749+
function getPropertyNameNodeForSymbolFromNameType(symbol: Symbol, context: NodeBuilderContext, singleQuote?: boolean, stringNamed?: boolean) {
77507750
const nameType = getSymbolLinks(symbol).nameType;
77517751
if (nameType) {
77527752
if (nameType.flags & TypeFlags.StringOrNumberLiteral) {
77537753
const name = "" + (nameType as StringLiteralType | NumberLiteralType).value;
7754-
if (!isIdentifierText(name, getEmitScriptTarget(compilerOptions)) && !isNumericLiteralName(name)) {
7754+
if (!isIdentifierText(name, getEmitScriptTarget(compilerOptions)) && (stringNamed || !isNumericLiteralName(name))) {
77557755
return factory.createStringLiteral(name, !!singleQuote);
77567756
}
77577757
if (isNumericLiteralName(name) && startsWith(name, "-")) {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//// [declarationEmitMappedTypePropertyFromNumericStringKey.ts]
2+
export const f = (<T>(arg: {[K in keyof T]: T[K] | string}) => arg)({'0': 0}); // Original prop uses string syntax
3+
4+
//// [declarationEmitMappedTypePropertyFromNumericStringKey.js]
5+
"use strict";
6+
exports.__esModule = true;
7+
exports.f = void 0;
8+
exports.f = (function (arg) { return arg; })({ '0': 0 }); // Original prop uses string syntax
9+
10+
11+
//// [declarationEmitMappedTypePropertyFromNumericStringKey.d.ts]
12+
export declare const f: {
13+
'0': string | number;
14+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
=== tests/cases/compiler/declarationEmitMappedTypePropertyFromNumericStringKey.ts ===
2+
export const f = (<T>(arg: {[K in keyof T]: T[K] | string}) => arg)({'0': 0}); // Original prop uses string syntax
3+
>f : Symbol(f, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 12))
4+
>T : Symbol(T, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 19))
5+
>arg : Symbol(arg, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 22))
6+
>K : Symbol(K, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 29))
7+
>T : Symbol(T, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 19))
8+
>T : Symbol(T, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 19))
9+
>K : Symbol(K, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 29))
10+
>arg : Symbol(arg, Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 22))
11+
>'0' : Symbol('0', Decl(declarationEmitMappedTypePropertyFromNumericStringKey.ts, 0, 69))
12+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
=== tests/cases/compiler/declarationEmitMappedTypePropertyFromNumericStringKey.ts ===
2+
export const f = (<T>(arg: {[K in keyof T]: T[K] | string}) => arg)({'0': 0}); // Original prop uses string syntax
3+
>f : { '0': string | number; }
4+
>(<T>(arg: {[K in keyof T]: T[K] | string}) => arg)({'0': 0}) : { '0': string | number; }
5+
>(<T>(arg: {[K in keyof T]: T[K] | string}) => arg) : <T>(arg: { [K in keyof T]: string | T[K]; }) => { [K in keyof T]: string | T[K]; }
6+
><T>(arg: {[K in keyof T]: T[K] | string}) => arg : <T>(arg: { [K in keyof T]: string | T[K]; }) => { [K in keyof T]: string | T[K]; }
7+
>arg : { [K in keyof T]: string | T[K]; }
8+
>arg : { [K in keyof T]: string | T[K]; }
9+
>{'0': 0} : { '0': number; }
10+
>'0' : number
11+
>0 : 0
12+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// @declaration: true
2+
export const f = (<T>(arg: {[K in keyof T]: T[K] | string}) => arg)({'0': 0}); // Original prop uses string syntax

0 commit comments

Comments
 (0)