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 conston the functions return value - Provide an explicit return type on the function (as your function definition, e.g.
return 1satisfies 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


