void is the return type of a function whose result does not matter: @returns {void}. In a callback type, (id: string) => void means the caller will ignore whatever the callback returns, so a callback that happens to return something is still accepted.
never is the type of something that cannot happen: a function that always throws, or a value after every possible case has been handled. TypeScript uses it to prove that code is exhaustive.
At a glance
| Use | JSDoc in a .js file | TypeScript in a .ts file |
|---|---|---|
| Returns nothing useful | /** @returns {void} */ | (): void |
| A callback whose result is ignored | /** @param {(id: string) => void} onSaved */ | (onSaved: (id: string) => void) |
| Never returns | /** @returns {never} */ | (): never |
Examples
/**
* @param {string} draft
* @param {(id: string) => void} onSaved
*/
export function save(draft, onSaved) {
const id = `draft-${draft.length}`;
onSaved(id);
}
/** @type {string[]} */
const saved = [];
// push returns a number; the void callback type accepts it and ignores the result.
save("Spring sale", (id) => saved.push(id));jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /** @typedef {"pending" | "shipped" | "delivered" | "refunded"} OrderStatus */
/**
* @param {never} value
* @returns {never}
*/
function unhandled(value) {
throw new Error(`Unhandled status: ${value}`);
}
/** @param {OrderStatus} status */
export function label(status) {
switch (status) {
case "pending":
return "Waiting to ship";
case "shipped":
return "On the way";
case "delivered":
return "Delivered";
default:
return unhandled(status);error TS2345: Argument of type '"refunded"' is not assignable to parameter of type 'never'.
}
}type OrderStatus = "pending" | "shipped" | "delivered" | "refunded";
function unhandled(value: never): never {
throw new Error(`Unhandled status: ${value}`);
}
export function label(status: OrderStatus) {
switch (status) {
case "pending":
return "Waiting to ship";
case "shipped":
return "On the way";
case "delivered":
return "Delivered";
default:
return unhandled(status);error TS2345: Argument of type '"refunded"' is not assignable to parameter of type 'never'.
}
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /**
* @param {string} message
* @returns {never}
*/
function fail(message) {
throw new Error(message);
}
/** @param {number | undefined} stock */
export function reserve(stock) {
if (stock === undefined) fail("Unknown product");
return stock - 1;
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Exhaustive checks with never
After a switch has handled every member of a union, the value left in default has type never. Passing it to a function that takes never type-checks only while that is true. Add a member to the union without a matching case, and the call fails (TS2345), pointing you at the switch that needs updating, as the second example shows.
Functions that never return
@returns {never} on a function that always throws tells TypeScript that code after a call to it is unreachable. In the third example, stock is number after if (stock === undefined) fail(…), because the fail call ends that path.
For that narrowing to work, the function needs the explicit @returns {never} and must be a declaration TypeScript can see, as here.
Gotchas
- A function declared
@returns {void}that returns a value is an error; a callback typed=> voidthat returns a value is not. The difference is deliberate, soarray.forEach((x) => list.push(x))works. undefinedandvoidare close but not the same: before TypeScript 5.1, a function typed to returnundefinedneeded an explicitreturn.
Questions
What does never mean in TypeScript?
A type with no values. A function returning never does not return at all, and a variable of type never can only exist in code TypeScript has proven unreachable.
Sources
- More on Functions: void and never · TypeScript handbook
- Narrowing: exhaustiveness checking · TypeScript handbook
Last reviewed 20 October 2026.