Can anyone please explain to me why ReturnType
can infer a function's exact return values when there's an if
statement, but only can infer types of the value when the function returns one guaranteed string or number value?
In testA
, ReturnType<typeof testA>
could successfully infer the return values, 1 and 2.
However, in the case of testB
(return one value), ReturnType<typeof testB>
can only infer the type, number
.
Why a function that returns only can guess literally the type of the return value which is number
It behaves the same with string
values. (second screenshot)
CodePudding user response:
This is related to type widening
The following resources will be useful:
- SO answer explaining the behaviour
- The TypeScript PR (referenced in the above answer) which explains the rules for when a literal type is widened or not
An explicit excerpt from the above PR outlines the behaviour observed
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:
function foo() { return "hello"; } function bar() { return cond ? "foo" : "bar"; } const c1 = foo(); // string const c2 = bar(); // "foo" | "bar"
A couple of simple ways to address this are:
- Leverage
as const
on the functions return value - Provide an explicit return type on the function (as your function definition, e.g.
return 1
satisfies the return type constraint, there is no need for inferrence and thus potential widening)
const testA = (v: boolean) => v ? 1 : 2; // (v: boolean) => 1 | 2
const testB = (v: boolean) => 1; // (v: boolean) => number
const constTestB = (v: boolean) => 1 as const; // (v: boolean) => 1
const typedTestB = (v: boolean): 1 => 1; // (v: boolean) => 1