📖 Scenario: You are building a simple program that handles different shapes. Each shape has a specific way to calculate its area. You want to make sure that if a new shape is added later, your program will remind you to handle it properly.
🎯 Goal: Create a TypeScript program that uses exhaustive checking with the never type to ensure all shape types are handled in a function.
📋 What You'll Learn
Create a union type called Shape with three shapes: circle, square, and rectangle
Create a variable called shape with a specific shape object
Create a function called calculateArea that uses a switch statement to handle each shape type
Use exhaustive checking with never in the calculateArea function to catch unhandled shapes
Print the area calculated by calculateArea
💡 Why This Matters
🌍 Real World
Exhaustive checking helps catch errors early when working with different types of data, such as shapes, events, or commands in real applications.
💼 Career
Understanding exhaustive checking with never is important for writing safe and maintainable TypeScript code, a valuable skill for frontend and backend developers.
Progress0 / 4 steps
1
Create the Shape union type and a shape variable
Create a union type called Shape with these exact types: { kind: 'circle', radius: number }, { kind: 'square', side: number }, and { kind: 'rectangle', width: number, height: number }. Then create a variable called shape with the value { kind: 'circle', radius: 5 }.
Typescript
Hint
Use a union type with | to combine the three shape types. Then create the shape variable with the exact object.
2
Add the calculateArea function skeleton
Create a function called calculateArea that takes a parameter shape of type Shape and returns a number. Inside the function, add a switch statement on shape.kind with empty cases for 'circle', 'square', and 'rectangle'.
Typescript
Hint
Define the function with the correct parameter and return type. Add a switch on shape.kind with cases for each shape kind.
3
Implement area calculations and add exhaustive checking
Inside the calculateArea function, return the correct area for each shape: for circle return Math.PI * shape.radius ** 2, for square return shape.side * shape.side, and for rectangle return shape.width * shape.height. After the switch, add a default case that assigns shape to a variable of type never to ensure exhaustive checking.
Typescript
Hint
Calculate each area using the correct formula. Use a default case with a never variable to catch unhandled shapes.
4
Print the area of the shape
Write a console.log statement to print the result of calling calculateArea with the shape variable.
Typescript
Hint
Call calculateArea(shape) and print the result using console.log.
Practice
(1/5)
1. What is the main purpose of using never in exhaustive checking in TypeScript?
easy
A. To declare a variable that can hold any value
B. To allow any type of value without restrictions
C. To ignore errors during compilation
D. To ensure all possible cases are handled in a switch or conditional
Solution
Step 1: Understand the role of never in exhaustive checks
never is used to represent values that should never occur, helping catch unhandled cases.
Step 2: Connect never usage to exhaustive case handling
By forcing a function to accept never, TypeScript ensures all cases are covered, or else a compile error occurs.
Final Answer:
To ensure all possible cases are handled in a switch or conditional -> Option D
Quick Check:
Exhaustive checking = catch all cases [OK]
Hint: Use never to catch missing cases in switch statements [OK]
Common Mistakes:
Thinking never allows any value
Using never to ignore errors
Confusing never with unknown type
2. Which of the following is the correct syntax for a helper function that uses never to enforce exhaustive checking?
easy
A. function assertNever(x: never): never { throw new Error('Unexpected value: ' + x); }
B. function assertNever(x: any): void { console.log(x); }
C. function assertNever(x: unknown): never { return x; }
D. function assertNever(x: never): void { return; }
Solution
Step 1: Identify correct parameter and return types
The helper function must accept a parameter of type never and return never because it throws an error.
Step 2: Check function body matches expected behavior
The function throws an error with the unexpected value, which is the standard pattern for exhaustive checks.
Final Answer:
function assertNever(x: never): never { throw new Error('Unexpected value: ' + x); } -> Option A
Quick Check:
Helper function with never param and throw = correct [OK]
Hint: Helper must take never and throw error to enforce checks [OK]
Common Mistakes:
Using any or unknown instead of never
Not throwing an error inside the function
Returning void instead of never
3. What will be the output of this TypeScript code?
type Shape = 'circle' | 'square';
function area(shape: Shape) {
switch (shape) {
case 'circle':
return 3.14 * 2 * 2;
// Missing case for 'square'
default:
return assertNever(shape);
}
}
function assertNever(x: never): never {
throw new Error('Unexpected shape: ' + x);
}
console.log(area('square'));
medium
A. Returns 12.56
B. Throws Error: Unexpected shape: square
C. Returns undefined
D. Compilation error due to missing case
Solution
Step 1: Analyze switch cases and input
The function handles 'circle' but not 'square', so at runtime, calling area('square') hits the default case.
Step 2: Understand assertNever behavior at runtime
The assertNever function throws an error with the unexpected shape, so the program throws a runtime error.
Final Answer:
Throws Error: Unexpected shape: square -> Option B
Quick Check:
Missing case causes runtime error when called [OK]
Hint: Missing case triggers runtime error when called [OK]
Common Mistakes:
Assuming missing case returns undefined
Thinking it returns a number for all inputs
Expecting compile error instead of runtime error
4. Identify the error in this TypeScript code using exhaustive checking:
type Direction = 'up' | 'down' | 'left';
function move(dir: Direction) {
switch (dir) {
case 'up':
return 'Moving up';
case 'down':
return 'Moving down';
default:
return assertNever(dir);
}
}
function assertNever(x: never): never {
throw new Error('Unexpected direction: ' + x);
}
medium
A. Missing case for 'left' in switch statement
B. assertNever function has wrong parameter type
C. Switch statement should not have a default case
D. Function move should return void instead of string
Solution
Step 1: Check all union cases in switch
The type Direction has 'up', 'down', and 'left', but 'left' is missing in the switch.
Step 2: Understand impact of missing case with assertNever
Missing 'left' causes default to call assertNever with a string, which is not never, causing a compile error.
Final Answer:
Missing case for 'left' in switch statement -> Option A
Quick Check:
All union cases must be handled [OK]
Hint: Check all union cases explicitly to avoid errors [OK]
Common Mistakes:
Ignoring missing union cases
Thinking default case covers all safely
Wrong assertNever parameter type
5. Given this code, how can you modify it to ensure exhaustive checking for all Status values?
type Status = 'success' | 'error' | 'loading';
function handleStatus(status: Status) {
switch (status) {
case 'success':
return 'Done';
case 'error':
return 'Failed';
// Missing 'loading' case
default:
return assertNever(status);
}
}
function assertNever(x: never): never {
throw new Error('Unexpected status: ' + x);
}
hard
A. Change the type Status to include only 'success' and 'error'
B. Remove the default case and rely on TypeScript errors
C. Add a case for 'loading' in the switch statement
D. Change assertNever parameter type to any
Solution
Step 1: Identify missing union case in switch
The 'loading' case is missing, so the switch is not exhaustive.
Step 2: Add missing case to ensure all Status values are handled
Adding case 'loading': with appropriate return ensures exhaustive checking and no runtime errors.
Final Answer:
Add a case for 'loading' in the switch statement -> Option C
Quick Check:
All union members must have cases [OK]
Hint: Add missing union cases to switch for full coverage [OK]
Common Mistakes:
Removing default case without adding missing cases
Changing type to avoid handling all cases
Using any instead of never in assertNever
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.