TypeScript - Never: Understanding the Bottom Type
Hello, aspiring programmers! Today, we're going to dive into one of TypeScript's more enigmatic types: the never
type. Don't worry if you're new to programming – I'll guide you through this concept step by step, just as I've done for countless students in my years of teaching. So, grab your favorite beverage, and let's embark on this exciting journey into the world of TypeScript!
What is the never type?
The never
type in TypeScript is often referred to as the "bottom type" or the "empty type." It represents a type that should never occur. Now, you might be thinking, "Why would we need a type that never happens?" Well, my curious friends, it's more useful than you might think!
When is never used?
- To represent impossible scenarios
- To handle exhaustive checks
- In functions that never return
Let's look at some examples to make these concepts clearer.
Example 1: Representing Impossible Scenarios
function throwError(message: string): never {
throw new Error(message);
}
let result = throwError("Oops! Something went wrong!");
console.log(result); // This line will never be reached
In this example, the throwError
function is guaranteed to throw an error and never return normally. Therefore, its return type is never
.
Think of it like this: if you're baking a cake and the recipe says "bake until never," you know that cake isn't coming out of the oven!
Example 2: Exhaustive Checks
type Shape = "circle" | "square" | "triangle";
function getArea(shape: Shape): number {
switch (shape) {
case "circle":
return Math.PI * Math.pow(5, 2);
case "square":
return 10 * 10;
case "triangle":
return (10 * 5) / 2;
default:
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
Here, never
helps us ensure we've covered all possible shapes. If we add a new shape to the Shape
type but forget to add a case for it in getArea
, TypeScript will give us an error. It's like having a helpful assistant that reminds you when you've forgotten something!
Example 3: Functions That Never Return
function infiniteLoop(): never {
while (true) {
console.log("This loop never ends!");
}
}
This function will run forever (or until your computer runs out of memory). Since it never finishes executing, its return type is never
. It's like telling your friend you'll stop talking "never" – they know they're in for a long conversation!
The never type vs. void
Now, you might be wondering, "How is never
different from void
?" Great question! Let's break it down.
void
The void
type is used when a function doesn't return any value, but it does complete its execution.
function logMessage(message: string): void {
console.log(message);
}
logMessage("Hello, TypeScript!"); // This function returns undefined
never
The never
type, on the other hand, is used when a function never completes its execution or always throws an error.
function failwithError(message: string): never {
throw new Error(message);
}
failwithError("This function never returns!");
Think of it this way: void
is like going to a store and coming back empty-handed, while never
is like setting out on a journey with no destination – you never come back!
Practical Uses of never
Let's look at some more practical examples where never
can be useful.
Example 4: Type Guards
type Square = { kind: "square", size: number };
type Circle = { kind: "circle", radius: number };
type Shape = Square | Circle;
function assertNever(x: never): never {
throw new Error("Unexpected object: " + x);
}
function getArea(shape: Shape) {
switch (shape.kind) {
case "square": return shape.size * shape.size;
case "circle": return Math.PI * shape.radius ** 2;
default: return assertNever(shape); // Error if shape is neither Square nor Circle
}
}
In this example, assertNever
helps us catch any case we might have missed. It's like having a safety net when you're learning to juggle types!
Example 5: Unreachable Code Detection
function neverReaches(): never {
while (true) {
// Some operation
}
console.log("This line will never be reached"); // TypeScript error
}
TypeScript is smart enough to know that the console.log
statement will never be reached, and it will give you an error. It's like having a GPS that tells you when you're trying to drive to a place that doesn't exist!
Methods and Properties of never
Now, you might be wondering if never
has any methods or properties. The truth is, never
doesn't have any of its own methods or properties because it represents a type that should never occur. However, it's still an important part of TypeScript's type system.
Here's a table summarizing what you can (or can't) do with never
:
Operation | Result | Explanation |
---|---|---|
Assign to never
|
✅ Allowed | Any type can be assigned to never
|
Assign never to other types |
❌ Not Allowed |
never can't be assigned to any other type |
Call methods on never
|
❌ Not Allowed | Since never should never occur, you can't call methods on it |
Use never in unions |
✅ Allowed but has no effect |
never is ignored in union types |
Use never in intersections |
✅ Allowed and results in never
|
Any type intersected with never results in never
|
Conclusion
And there you have it, my dear students! We've journeyed through the land of never
, exploring its nooks and crannies. Remember, never
is like that friend who always cancels plans – they never show up, but they're still important to keep in mind!
Understanding never
might seem tricky at first, but with practice, you'll find it's an invaluable tool in your TypeScript toolkit. It helps make your code more robust, catches potential errors, and even makes you think more deeply about your function's behavior.
Keep coding, keep learning, and never say never to trying new things in TypeScript! Until next time, may your compilation errors be few and your type inferences be strong!
Credits: Image by storyset