Into the void
of TypeScript
The TypeScript type void
refers to function return value that is meant to be ignored.refs:void
Just like any other type you can annotate variables with void
. But its not useful there. It's only useful in the context of functions.
Inferred void
type
When a function doesn't explicitly return a valuenotes:explicitReturn, it usually means that its return value does not serve a purpose and can be ignored. So TypeScript infers it to be of type void
.
function sayHello() {
console.log("hello");
}
Above the inferred return type of sayHello
is void
.
void
return type in literal function defnition
Of a literal function definitionnotes:fd with a void
return type, TypeScript will give you error if you return anything other than undefined
.notes:undefined If TypeScript would allow returning other values, it wouldn't create a type system violation. This error reporting is helpful for catching bugs that might arise from refactoringrefs:void-undefined:
// 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;
}
}
void
return type in contextual function type
Contextual typing occurs when the type of an expression is implied by its location.refs:contextual-typing
A contextual function type provides context to the function that is placed in the context.
A contextual function type with void
return type when implemented, can return any value, but it will be ignored.
This behavior exists so that the following code is valid even though Array.prototype.push
returns a number and the Array.prototype.forEach
method expects a function with a return type of void
.refs:assignability-of-func
const src = [1, 2, 3];
const dst = [0];
src.forEach((el) => dst.push(el));
A question that might be on your mind is:
When an implementation of a contextual function type with a
void
return type is assigned to a variable, what type does this variable have?
Whatever that function returns, the variable would be of type void
. This is good because the return value of the function was not intended to be used.
type voidFuncType = () => void;
const f: voidFuncType = () => {
return true;
};
const v = f();
Above the type of v
is void
.
void
vs undefined
A contextual function type with undefined
return type when implemented, must return undefined
. For the case of void
, the return value doesn't matter.
type undefinedFuncType = () => undefined;
const f: undefinedFuncType = () => {
return true;
};
TypeScript will yell at this code.
void
vs any
type anyFuncType = () => any;
type voidFuncType = () => void;
const anyFunc: anyFuncType = () => {
return "f1";
};
const voidFunc: voidFuncType = () => {
return "f2";
};
const anyValue = anyFunc();
const voidValue = voidFunc();
anyValue.trim(); // No error
voidValue.trim(); // Error
With void
return type we can ensure that the consumers of voidFunc
will get an error when accessing properties of its return value. And with any
there is no error, and no help from TypeScript!
Notes
- [explicitReturn] A function that explicitly returns something has a
return
statement with a return value. - [fd] It doesn't matter if it is the definition a function statement or function expression.
- [undefined]
undefined
is always assignable tovoid
.
References
- [void]
no-invalid-void-type
typescript-eslint rule - [void-undefined] Why does TypeScript have both
void
andundefined
? - [contextual-typing] Contextual Typing, TypeScript Handbook
- [assignability-of-func] Assignability of Functions, More on Functions, TyeScript Handbook