Skip to content

Return type incorrectly inferred as voidΒ #57840

Open
@fabiospampinato

Description

@fabiospampinato

πŸ”Ž 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

https://www.typescriptlang.org/play?ts=5.5.0-dev.20240318#code/FAFwngDgpgBAYgORgXhgCgJQoHwwAoBOA9gLYCWAzlADwCuAdgCZQBmZ9UjuAPjA82w6MA3MGABjIvQogYLegEYAXPCSpMOGAG9gMPTAJQQtAvVEBfURKky59AEwrEKdFmS4d+g0ZP0+TVnZOC1EgA

πŸ’» 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( () => {/* ... */} );

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions