Skip to content

Number-like string keys become numbers after compiling to type declarations #51395

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
calebmer opened this issue Nov 3, 2022 · 1 comment
Closed
Labels
Duplicate An existing issue was already created

Comments

@calebmer
Copy link

calebmer commented Nov 3, 2022

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);

(Playground)

🔎 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.

@MartinJohns
Copy link
Contributor

Duplicate of #50358. Used search terms: number string declaration in:title

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Nov 3, 2022
@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants