Never type and unreachable code in Typescript - Time & Space Complexity
We want to see how the program's steps grow when using the never type and unreachable code.
Are there any repeated actions or does the program stop early?
Analyze the time complexity of the following code snippet.
function fail(message: string): never {
throw new Error(message);
}
function example(value: number) {
if (value > 0) {
return value;
} else {
return fail("Value must be positive");
}
}
This code throws an error when the input is not positive, using the never type to mark unreachable code after throwing.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: There are no loops or repeated steps; the function either returns or throws immediately.
- How many times: Each call runs a fixed number of steps once.
Execution steps stay the same no matter the input size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 5 steps |
| 100 | 5 steps |
| 1000 | 5 steps |
Pattern observation: The number of steps does not increase with input size; it stays constant.
Time Complexity: O(1)
This means the program takes the same amount of time no matter the input size.
[X] Wrong: "The never type causes the program to run forever or do extra work."
[OK] Correct: The never type just marks code that never finishes normally, so it stops immediately without extra steps.
Understanding unreachable code and the never type helps you reason about program flow clearly and avoid mistakes in real projects.
"What if the fail function used a loop before throwing? How would the time complexity change?"
Practice
never type represent in TypeScript?Solution
Step 1: Understand the
Thenevertype meaningnevertype is used for functions or expressions that never complete normally, such as those that throw errors or run infinite loops.Step 2: Compare with other types
Other options describe common types like any, null, or optional, which are different fromnever.Final Answer:
A function that never returns normally, like one that always throws an error or loops forever. -> Option DQuick Check:
nevermeans no normal return [OK]
- Confusing never with void or any
- Thinking never means optional or nullable
- Assuming never is a value type
never in TypeScript?Solution
Step 1: Check function return type and body
A function returningnevermust not return normally. Throwing an error fits this.Step 2: Validate each option
function fail(): never { throw new Error('Fail'); } throws an error, so it never returns normally. function fail(): void { return; } returns void normally. function fail(): never { return null; } tries to return null, which is invalid for never. function fail(): string { throw new Error('Fail'); } returns string but throws, so return type mismatches.Final Answer:
function fail(): never { throw new Error('Fail'); } -> Option AQuick Check:
Throw error matches never return [OK]
- Returning a value in a never function
- Using void instead of never
- Returning null or undefined in never
function check(value: string | number) {
switch (typeof value) {
case 'string':
return 'string';
case 'number':
return 'number';
default:
const _exhaustiveCheck: never = value;
return _exhaustiveCheck;
}
}
console.log(check(42));Solution
Step 1: Analyze the switch cases
The function handles 'string' and 'number' types explicitly, so the default case is unreachable for these inputs.Step 2: Check the call and output
Callingcheck(42)matches the 'number' case, so it returns 'number'. The default case withneveris never reached.Final Answer:
'number' -> Option BQuick Check:
Handled all cases, returns 'number' [OK]
- Thinking default case runs for known types
- Confusing never with runtime errors
- Expecting compilation error for unreachable default
function assertNever(x: never): never {
throw new Error('Unexpected value: ' + x);
}
function process(value: string | number) {
if (typeof value === 'string') {
return 'string';
} else if (typeof value === 'number') {
return 'number';
} else {
return assertNever(value);
}
}Solution
Step 1: Understand the function purpose
assertNeveris used to catch unexpected values at compile time by requiring anevertype.Step 2: Analyze the
All possible typesprocessfunctionstringandnumberare handled. The else branch is unreachable, sovalueisneverthere, making the call valid.Final Answer:
No error; code is correct and safe. -> Option CQuick Check:
Unreachable else means value is never [OK]
- Thinking assertNever is called with string or number
- Confusing never return with void
- Assuming else branch always runs
type Shape = { kind: 'circle', radius: number } | { kind: 'square', size: number };
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2;
// Missing case for 'square'
}
}Solution
Step 1: Identify missing case problem
The 'square' case is missing, so the switch is not exhaustive.Step 2: Use never type to catch missing cases
Adding adefaultcase that calls a function requiringneverforces TypeScript to check exhaustiveness and report missing cases.Final Answer:
Add adefaultcase that calls a function acceptingneverto catch unhandled cases. -> Option AQuick Check:
Use never in default to enforce exhaustiveness [OK]
- Assuming TypeScript warns without default never
- Returning default values silently
- Using any to bypass type safety
Ready to prove it?
Pass the test and this pattern moves unknown
