Daniel
Daniel

Reputation: 11172

TypeScript struggling with simple type inference for string literal

I ran into a problem with type inference, and tried to create the smallest reproducible example possible

type Options = { value: 'a' | 'b' }

const getOption = (): Options => {
    const result = { value: 'a' };
    return result;
}

Error

Type '{ value: string; }' is not assignable to type 'Options'.

__ Types of property 'value' are incompatible.

____ Type 'string' is not assignable to type '"a" | "b"'


(I'm not asking for a solution. I want to know why why TypeScript can't infer this)

I can return the result in a single operation without the error. I assume TypeScript is inferring the result variable to be of the type { value: string } instead of { value: 'a' }

To fix it I can change the result line to cast the string value to the literal it actually is, but it seems beyond silly.....

const result = { value: ('a' as 'a') };

Question

How come this is necessary? I'm usually always impressed about the depth of TypeScript's type inference, but for some reason it is struggling with this simple problem

Upvotes: 2

Views: 1147

Answers (2)

bam
bam

Reputation: 106

I think it caused by value you assigned to result const. It's an object and const declaration means that result reference couldn't be changed. But it doesn't guarantee that you won't change a property inside object value. So, we (and TS) can't say surely that value will be 'a' all the time. Thus referenced object has a shape of

{ value: string }

and TS inferred result as on object of that shape.

Upvotes: 0

asnaeb
asnaeb

Reputation: 745

You can use an as const assertion instead:

type Options = { value: 'a' | 'b' }

const getOption = (): Options => {
    const result = { value: 'a' } as const;
    return result;
}

this will tell the compiler that the type of result is {value: "a"} and not {value: string}

Upvotes: 4

Related Questions