Description
π Search Terms
- return type, void, infer, undefined
π Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about
β― Playground Link
π» Code
type FN = () => Promise<undefined> | undefined;
const fn1: FN = () => {
return;
};
const fn2: FN = () => {
return undefined;
};
π Actual behavior
fn1
is detected as returning void
, while fn2
is detected as returning undefined
.
π Expected behavior
I'm not sure it makes sense to me that the inferred type for these kinds of function is void
rather than undefined
, I would expect the more precise type to be inferred in this case.
Mainly there's no difference in JS between doing a return;
and a return undefined;
, unless .toString()
is called on the function containing that, so TS differentiating between return;
and return undefined;
seems a bit weird to me.
Presumably this is something that has been considered and returning void
is done on purpose and it's actually better on average, and requiring an explicit return undefined;
makes sense, but I'd like to point out that there are some detectable cases where one is not return
-ing to skip the following code, but one is explicitly returning undefined
for no other reason than to be explicit about it, for example in this case, where the return statement is the last statement of the function, and it's not even inside an else
branch. Like there is no other purpose to that return
than to mean, in every way, what the longer return undefined;
expresses, so perhaps the logic that decides whether void
or undefined
should be the returned type could be refined to account for this specific scenario.
Also if I'm passing a function like that as an argument that accepts () => undefined
I feel like that should be taken into consideration, and the function in that case should "obviously" be considered as returning undefined
rather than void
.
Additional information about the issue
I stumbled on this issue because at one point I'm accepting a function that has the following interface: () => (Promise<undefined> | undefined)
, the idea is that if the function returns a promise I'll call its then
function, and if it doesn't I'll call the then
function on a fallback value, so I'll just end up calling something called then
either way. Example code:
const FAKE_PROMISE = {
then: fn => fn ()
};
const return = myFn() || FAKE_PROMISE;
return.then( () => {/* ... */} );