Understanding the difference between Typescript’s void and never

Thomas James Byers
2 min readJun 16, 2019

--

TLDR: A function which runs to completion without returning anything has a return type of void, but a function which never completes execution has a return type of never.

The best way to illustrate the difference is with an example. A function which always throws an exception will never finish executing. Compare this to a function which does some work and then finishes without a return statement.

const thisThrows = (): never => {
throw('someError');
return 'thisNeverHappens';
}
const thisDoesNotReturnAValue = (): void => {
someGlobal = 1 + 2;
}

Why does this distinction matter? It’s all down to how the calling code handles the return value. If the return value can be void the caller must handle that case.

Imagine a function which can return either a string or void, it is not safe to call toUpperCase on the return value until you have checked to confirm that it really is a string.

const returnValue = getAStringOrVoid();returnValue.toUpperCase(); // this is unsafeif (typeof returnValue === 'string') {
returnValue.toUpperCase(); // this is safe
}

But if the function sometimes returns a string and sometimes never returns at all it is perfectly safe to call toUpperCase.

const anotherReturnValue = getAStringOrThrow();
anotherReturnValue.toUpperCase(); // this is safe

Let’s think about why this is.

When you call `getAStringOrThrow` one of two things can happen. It could return a string in which case it would be fine to call toUpperCase because we know strings have that method. Or it could throw an exception in which case it is also safe to call toUpperCase because that line will never be executed. Instead code execution will “go backwards” until it reaches an error handler such as a try/catch block.

--

--