124

In TypeScript, you can annotate a function as returning void:

function fn1(): void {
  // OK
}

function fn2(): void {
  // Error
  return 3;
}

You can also annotate a function to return undefined:

function fn3(): undefined {
  // OK
  return;
}

function fn4(): undefined {
  // Error
  return 3;
}

So it seems that if you call a function returning void, you'll always get back the value undefined. Yet you can't write this code:

function fn5(): void {
}
let u: undefined = fn5(); // Error

Why isn't void just an alias for undefined? Does it need to exist at all?

0

3 Answers 3

223

void has special meaning in function return types, and is not an alias for undefined. Thinking of it this way is very wrong. Why?

The intent of void is that a function's return value will not be observed. This is very different from will be undefined. It's important to have this distinction so that you can properly describe functions like forEach. Let's consider a freestanding version of Array#forEach, written with undefined instead of void in the callback return position:

declare function forEach<T>(arr: T[], callback: (el: T) => undefined): void;

If you tried to use this function:

let target: number[] = [];
forEach([1, 2, 3], el => target.push(el));

You'd get an error:

Type "number" is not assignable to type "undefined"

This is a correct error - you said you wanted a function that returned the value undefined, but you actually provided a function that returned the value number because that's what Array#push returns!

Using void instead means that forEach promises not to use the return value, so it can be called with a callback that returns any value

declare function forEach<T>(arr: T[], callback: (el: T) => void): void;
let target: number[] = [];
// OK
forEach([1, 2, 3], el => target.push(el));

Why not just use any ? If you're actually the one implementing forEach, you really don't want that - having an any floating is a dangerous thing that can defeat typechecking very easily.

The corollary to this is that if you have some function expression whose return type is void, you cannot say with any certainty that the result of invoking that function is undefined.

Again, void is not an alias for undefined and an expression of type void may have any value, not just undefined

In a function body whose return type is explicitly listed as void, TypeScript will stop you from "accidently" returning a value, even though this wouldn't create a type system violation. This is helpful for catching bugs that appear from a refactoring:

// Old version
function fn(arr: number[]): void {
  const arr1 = arr.map(x => {
    return 3;
  });
}

// New version
function fn(arr: number[]): void {
  for (const x of arr) {
    // Oops, meant to do something else
    return 3;
  };
}
Sign up to request clarification or add additional context in comments.

13 Comments

Excellent explanation, thank you! One question I still have is: why does TS allow assigning the return value of a void function if we shouldn't trust return values from void functions at all? function b(): void {}; const y = b()
As a corollary, does this mean that a callback that can optionally return some value (let's say a number) should be declared as returning number | undefined rather than number | void?
Then what is the difference between void and unknown? I thought the unknown type was the "anything in, nothing out" type? - which fits perfectly for function return types that are not observed.
Unfortunately, it seems like TypeScript sometimes does treat void like undefined, which can lead to trouble: gist.github.com/rkjnsn/0435efb3af33d74b06d337f0f2706224
Given the JS runtime that this would compile to, this all feels too theoretical and borderline misleading.
|
2

https://www.typescriptlang.org/docs/handbook/2/functions.html#void https://www.typescriptlang.org/docs/handbook/2/functions.html#return-type-void enter image description here

void is not the same as any, nor the same as undefined.

Comments

0

void describes the necessity of the existence of the parameters or the return value of a function. It's not intended to describe a value.

When we are not talking about functions, there is no concept of void.

When we say "The variable is of type void." It means the source of the value of the variable is a function which does not have to return a value.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.