Why does the Typescript compiler infer return type of functions as `primitive type` while the return value is a known value?
Asked Answered
Y

2

6

As you can see in below code, the TS compiler infers the type as :

const message = Math.random() > 0.5 ? "hello, can you here me" : null;

So message variable is inferred as "hello, can you here me" | null, which makes sense, as there are two absolute possible values, however in this example bellow the return value is still an absolute value, but the getName type is string primitive type not John Gump

const getName = () => "John Gump";
Yoicks answered 22/11, 2022 at 6:50 Comment(1)
Did you mean to execute that function before assigning it to getName? Right now, its type is a function returning a string.Albite
R
3

All the rules about widening of literal types which concern this question were written down in PR/#10676.


Let's look at the first expression:

const message = Math.random() > 0.5 ? "hello, can you here me" : null;

The first rule applicable to this statement is the following:

The type of a string or numeric literal occurring in an expression is a widening literal type.

The expression itself is inferred to be a "widening literal type" which is a literal type that can be widened by the compiler as appropriate.

But is it appropriate in our example? The PR states that

The type inferred for a const variable or readonly property without a type annotation is the type of the initializer as-is.

As message is a const variable, the type of the widened literal type of the expression is not widened and stays "hello, can you here me" | null.

The compiler would find widening appropriate for a let variable.

let message = Math.random() > 0.5 ? "hello, can you here me" : null;
//  ^? message: string | null

When it comes to inferred function return types, the PR states that

In a function with no return type annotation, if the inferred return type is a literal type (but not a literal union type) and the function does not have a contextual type with a return type that includes literal types, the return type is widened to its widened literal type

Let's look again at the function:

const getName = () => "John Gump";

We can see that indeed the functions return type would be a literal type "John Gump". This is not a union and there is also no contextual type which concludes to the return type being widened to its widened literal type string.

Rebroadcast answered 22/11, 2022 at 9:5 Comment(0)
G
0

Math.random() return value between 0 and 1. Therefore message var always be null.

Guddle answered 22/11, 2022 at 6:59 Comment(3)
In runtime yes, but not from the TS point of view.Yoicks
However, I changed 3 to 0.5, although the inference will remain the same, but the question will become more valid. thanks.Yoicks
That's not even really what the question is asking about. I think this is a comment.Albite

© 2022 - 2024 — McMap. All rights reserved.