Number-like string keys become numbers after compiling to type declarations
Bug Report
TypeScript outputs an object with string keys that can be parsed as numbers ({"1": T}) as an object with number keys when processed by an object map (output is {1: T} after object map).
When you do keyof on the object type with string keys after an object map, you get the keys back as strings as expected ("1"). However, if you keyof on the object type TypeScript outputs to a .d.ts file you get back a number (1).
I ran into this when moving some code between TypeScript projects. So it was consuming a generated .d.ts instead of the original type. So for some f(x) it works works as expected when x is in the same project as f but when f is in a different project to x there's an issue.
const source = {"1": 1, "2": 2, "3": 3};
declare function objectMap<T>(object: T): {[K in keyof T]: string};
export const result = objectMap(source);
declare function objectKeys<T>(object: T): keyof T;
// Type is `"1" | "2" | "3"`. Expected!
export const keys1 = objectKeys(result);
// This is the type you get for `result` when compiling to `.d.ts`.
// (See `.d.ts` output for confirmation.)
export declare const resultCopiedFromGeneratedDeclaration: {
1: string;
2: string;
3: string;
};
// Type is `1 | 2 | 3`. Unexpected
export const keys2 = objectKeys(resultCopiedFromGeneratedDeclaration);
š Search Terms
Object map turns string keys into numbers
š Version & Regression Information
4.8.4
- This is the behavior in every version I tried (I tried versions back to 3.3.3 in the playground)
⯠Playground Link
Playground link with relevant code
š» Code
const source = {"1": 1, "2": 2, "3": 3};
declare function objectMap<T>(object: T): {[K in keyof T]: string};
export const result = objectMap(source);
declare function objectKeys<T>(object: T): keyof T;
// Type is `"1" | "2" | "3"`. Expected!
export const keys1 = objectKeys(result);
// This is the type you get for `result` when compiling to `.d.ts`.
// (See `.d.ts` output for confirmation.)
export declare const resultCopiedFromGeneratedDeclaration: {
1: string;
2: string;
3: string;
};
// Type is `1 | 2 | 3`. Unexpected
export const keys2 = objectKeys(resultCopiedFromGeneratedDeclaration);
š Actual behavior
Type of keys2 is 1 | 2 | 3.
š Expected behavior
Type of keys2 is "1" | "2" | "3" since that's the same as if the parameter to objectKeys() was in the same project and not imported from a .d.ts file.
Iād also be happy with {[K in keyof T as ``${K}``]: number} forcing the mapped object to have string keys instead of number keys.
Duplicate of #50358. Used search terms: number string declaration in:title
This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.