Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type narrowing & never functions

When using type narrowing with TypeScript, never functions do not react the same way every time.

const getValue = () => {
  const value = process.env.VARIABLE
  if (!value) process.exit(1)
  return value
}

In the example below, getValue inferred type is () => string, because value is typed string | undefined, and TypeScript is able to identify that the remaining code after process.exit is unreachable, and the return value is always a string.

const exit = () => {
  return process.exit(1)
}

const getValue = () => {
  const value = process.env.VARIABLE
  if (!value) exit()
  return value
}

In this second example, exit is typed () => never, and getValue inferred type is () => string | undefined, because TypeScript is unable to detect that the rest of the function is unreachable if value does not exists. However, if I add a return before the exit call (so return exit()), it works as desired.

Why does it works like this? Is there a way to make it work in the second case?

like image 321
ghivert Avatar asked Oct 24 '25 07:10

ghivert


1 Answers

TypeScript's support for functions that return never, as implemented in microsoft/TypeScript#32695, only works if the function type is explicitly annotated to return never. It would be nice if the type checker could just infer that, but allowing that would make control flow analysis much harder to implement so that it performs well. As it says in the above-liked PR, "this particular rule exists so that control flow analysis of potential assertion calls doesn't circularly trigger further analysis".

So, to get the behavior you're looking for, you should annotate exit as being of type () => never, like this:

const exit: () => never = () => {
  return process.exit(1)
}

and then it just works:

const getValue = () => {
  const value = process.env.VARIABLE
  if (!value) exit()
  return value
}
// const getValue: () => string

Playground link to code

like image 114
jcalz Avatar answered Oct 25 '25 21:10

jcalz