Skip to content

String literal types from typeof is reduced to string when passing through a generic function that "boxes" the type #22758

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
benjajaja opened this issue Mar 21, 2018 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@benjajaja
Copy link

TypeScript Version: 2.7.2

Search Terms: string literal, typeof, generic, structuring, boxing

Code

type StringLiteral = 'A' | 'B';
const map = (genders: StringLiteral[]): { gender: StringLiteral }[] =>
    genders.map(gender => ({ gender }));
// OK

const CONST_A = 'A';
const CONST_B = 'B';
type StringLiteralFromTypeof = typeof CONST_A | typeof CONST_B;

// StringLiteral and StringLiteralFromTypeof have the same type, when you hover them.

const map_typeof_no_generics_struct = (gender: StringLiteralFromTypeof): { gender: StringLiteralFromTypeof } =>
    ({ gender });
// OK if we struct (or "box") but don't pass through a generic function

const map_typeof_map_struct = (genders: StringLiteralFromTypeof[]): { gender: StringLiteralFromTypeof }[] =>
    genders.map(gender => ({ gender }));
// Error: inferred type is { gender: string }[]

const map_typeof_map_nonstruct = (genders: StringLiteralFromTypeof[]): StringLiteralFromTypeof[] =>
    genders.map(gender => gender);
// OK: if not structured into object or array, the type is inferred correctly

const identity = <T>(v: T) => v;
const map_typeof_any_generic = (gender: StringLiteralFromTypeof): { gender: StringLiteralFromTypeof } =>
    identity({ gender });
// Error: inferred type is { gender: string }[]

const map_typeof_any_generic_nonstruct = (gender: StringLiteralFromTypeof): StringLiteralFromTypeof =>
    identity(gender);
// OK: if not structured into object or array, the type is inferred correctly

Expected behavior:
A string literal type that was constructed from typeof someVar | ... should behave the same as a string literal type defined from string values 'val' | ....

Actual behavior:
When both passing through a generic function, AND structuring or "boxing" the type into an object or array, then the type is reduced to string.

Playground Link: link to see inferred types

Related Issues:
unknown

@RyanCavanaugh
Copy link
Member

StringLiteral and StringLiteralFromTypeof are not identical, even though they have the same display text. See #22211

@mhegazy mhegazy added the Duplicate An existing issue was already created label Mar 26, 2018
@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jul 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants