void

Marks a function as returning no useful value, while still accepting callbacks that return one.

Signature
type voidFunc = () => void
  • Added in TypeScript 1.0

Errors

A literal function declaration annotated `: void` may not `return` a value — "Type 'X' is not assignable to type 'void'."

Changelog

  • PHP 2.0Under strictNullChecks, undefined remains assignable to void, but null does not (unless strictNullChecks is off).
  • PHP 3.xContextual typing rules confirmed: a function assigned to a void-returning function type may return any value, and the result is typed void at the call site.

void is the return type of a function that produces no meaningful value. Written on a declaration, it is a real constraint: function log(): void may not return anything.

The rule that surprises everyone

Written on a function type, void is not a constraint on the implementation. A contextual function type with a void return, such as type VoidFunc = () => void, can be satisfied by a function that returns anything at all; the value is simply ignored, and at the call site the result is still typed void.

This is deliberate. It is what makes src.forEach((el) => dst.push(el)) legal — push returns a number, forEach wants a void callback — and it is why void is the right annotation for callback parameters whose result you intend to discard. Use undefined instead when you really do require the function to hand back undefined.

The other place void appears is Promise<void>, the type of an async function that resolves with nothing. Awaiting it is still meaningful: you are waiting for completion, not for a value.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Annotating an event handler or subscriber whose return value the caller discards
  • Declaring `Promise<void>` for an async operation you only await for completion
  • Typing a callback parameter so array methods like forEach accept expression-bodied arrows

Frequently asked questions

Why does TypeScript allow a function returning a value where void is expected?

Because a contextual function type with a `void` return means the caller ignores the result, not that the function must produce nothing. That rule exists so `arr.forEach(x => list.push(x))` type-checks even though `push` returns a number. A literal declaration annotated `: void` is different — there, returning a value is an error.

What is the difference between void and undefined in TypeScript?

`void` means "the return value is not to be used"; `undefined` means the value is specifically `undefined`. `undefined` is assignable to `void`, but a function type returning `undefined` rejects an implementation that returns something else, while a `void` one accepts it. Use `undefined` when the caller genuinely reads the result.

What does Promise<void> mean?

It is the type of an async function that finishes but resolves with no value — `await` it to sequence work, not to obtain data. `async function f(): Promise<void>` may contain bare `return;` statements. If callers need a result, return `Promise<T>` instead.

More examples

Why forEach accepts an expression-bodied arrow

Prints `[ 0, 1, 2, 3 ]` then `undefined 5`. The first assignment works because `void` in a callback position means "the result is discarded", not "the result is undefined". Switching the annotation to `undefined` makes the same arrow an error, which is exactly the difference between the two types.

Example · typescript
const src = [1, 2, 3];
const dst: number[] = [0];

// forEach's callback returns void; push returns number. Still legal.
src.forEach((el) => dst.push(el));
console.log(dst); // [ 0, 1, 2, 3 ]

// The same function typed to return undefined is rejected by tsc:
type StrictVoid = (n: number) => undefined;
// const bad: StrictVoid = (n) => dst.push(n);
// Error: Type 'number' is not assignable to type 'undefined'.

const ok: StrictVoid = (n) => { dst.push(n); return undefined; };
console.log(ok(9), dst.length);

Promise<void> and awaiting for completion

Prints `[ 'a', 'b', 'c', 'd' ]` then `undefined`. `Promise<void>` says the operation completes but resolves with no value, so awaiting it is about ordering rather than data. The sequential `for…of` keeps the output order deterministic; `Promise.all` would not.

Example · typescript
const written: string[] = [];

async function save(record: string): Promise<void> {
  await Promise.resolve();
  written.push(record);
}

async function saveAll(records: string[]): Promise<void> {
  for (const r of records) {
    await save(r);
  }
}

await saveAll(["a", "b", "c"]);
const nothing = await save("d");
console.log(written);
console.log(nothing);

Discussion

  • Be the first to comment on this lesson.