2

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

2
  • 3
    Well, return { value: 'a' } works fine: Playground Link I guess the check through reference for object not being changed is expensive for the TS compiler, hence it's not performed. You can also say const result = { value: 'a' } as const; or const result: Options = { value: 'a' }; but seems a bit redundant. Commented Aug 23, 2022 at 9:34
  • You can add the type the result variable like this: const result: Options = { value: 'a' };. Commented Aug 23, 2022 at 9:36

2 Answers 2

5

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}

Sign up to request clarification or add additional context in comments.

3 Comments

Isn't the return type more like { value: 'a' } instead of Options now? It's assignable, but { value: 'b' } cannot happen with this declaration.
I guess he will do {value: 'b'} as const as well when he needs it. Type of getOption is still Options tho
@MikeS. the return type is Options - that's the annotation the function has. And it returns something structurally compatible to Options, this the typing is correct.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.