When âNothingâ Doesnât Mean the Same Thing: Understanding void vs never in TypeScript
The difference between void and never isnât about returning nothing, but about whether execution continues or stops entirelyâshifting your thinking from values to control flow.
Thereâs a moment when learning TypeScript where two words start to blur together.
void and never.
At first glance, they seem to describe the same idea:
âThis function doesnât return anything.â
But that intuition turns out to be misleading.
Because in TypeScript, they are not describing the same thing at all.
The Subtle Misunderstanding
The confusion usually comes from how we think about functions.
We tend to think in terms of values:
- Does this function return something?
- Or does it return nothing?
So we map:
void â returns nothing
never â also returns nothingAnd thatâs where things go wrong.
Because TypeScript is not modeling values here.
Itâs modeling control flow.
What void Actually Means
When a function is typed as void, it doesnât mean:
âThis function returns nothingâ
It means:
âThis function returns, but whatever it returns is irrelevantâ
In JavaScript, every function technically returns something.
function log() {
console.log("hi")
}This returns undefined.
TypeScript simply tells you:
âDonât rely on the return value.â
So a void function is one that:
Completes normally â and execution continuesWhat never Actually Means
never describes something very different.
It means:
âThis function does not return at allâ
Not âreturns nothingâ.
But:
âThere is no point after this functionâ
function fail(): never {
throw new Error("Something went wrong")
}Or:
function loop(): never {
while (true) {}
}In both cases:
Execution never reaches the endThe Real Difference
The difference becomes clearer when you stop thinking about values and start thinking about flow.
void â function ends â program continues
never â function does not end â program does not continueThis is not about what is returned.
Itâs about whether execution can move forward.
Why This Distinction Matters
Consider this:
function getValue(x: string | null): string {
if (x === null) {
throw new Error("Invalid")
}
return x
}This works because TypeScript understands something subtle:
throw â never â execution stopsSo after that condition:
x is guaranteed to be a stringIf that function were treated like void, TypeScript would assume:
execution might continueAnd suddenly, the type safety breaks down.
Where the Confusion Comes From
Part of the confusion is that both void and never often appear in places where ânothingâ seems to happen.
function log(): void {}
function fail(): never {}They look similar.
But they describe two completely different realities:
void â âI finish, but donât give you anything usefulâ
never â âI never finish at allâA Shift in Thinking
The key shift is this:
Stop asking:
âDoes this function return a value?â
Start asking:
âDoes execution continue after this function?â
That one question separates void from never.
The Bigger Insight
This distinction reveals something deeper about TypeScript.
Types are not just about values.
They are also about:
What paths of execution are possible
void represents a normal path.
never represents an impossible one.
And once you see that, the confusion disappears.
Because youâre no longer thinking about ânothingâ.
Youâre thinking about what can happen next.