TypeScript Typed Function void Should Not Compile

Viewed 55

In the four functions below, the first two correctly return a number and the TypeScript compiler compiles them.

The third correctly causes a TypeScript compilation error but the fourth does not even though I expected it would?

// OK
let addNumbers: (a: number, b: number, c: number) => number = function (a, b, c) {
    return a + b + c;
};

// OK
let addNumbersTwo = function (a: number, b: number, c: number): number {
    return a + b + c;
};

// Correct compilation error
let addNumbersThree = function (a: number, b: number, c: number): void {
    return a + b + c;
};

// Should not compile? Should give same error as addNumbersThree above
let addNumbersFour: (a: number, b: number, c: number) => void = function (a, b, c) {
    return a + b + c;
};

TypeScript Playground example

1 Answers

That's because (whatever) => whatever is assignable to (whatever) => void.

Since a void returning function is expected to discard whatever nonexistent return value it has.

someVoidReturningFunction(args); // result doesn't get assigned or used.

It doesn't matter if in reality someVoidReturningFunction actually does return a value, and it just gets discarded.

In short: Giving your functions an explicit return value of void is a sign that consuming code should not care about the returned result.

Here's an example from the docs:

function callMeMaybe(callback: () => void) {
    callback();
}
let items = [1, 2];
callMeMaybe(() => items.push(3));

Technically speaking, items.push(3) will return a number (the new length of items). However, specifying a void callback actually allows us to pass a callback with any return value, and indicate that the return value will be discarded.


The same reasoning applies to missing arguments.

let foo: ((a: number, b: number) => number) = () => 42; // compiles

Because you can still call foo(1, 2) and get a number, even if those variables are unused in practice.

Related