In TypeScript, switch statements help in controlling complex conditional operations where multiple conditions are to be handled separately. This guide will explore how to use switch statements in TypeScript effectively, including creating exhaustive switches for type safety.
Basics of TypeScript switch statement
A switch statement in TypeScript evaluates an expression and attempts to match the expression's value to a case label. If a match is found, the code associated with that case is executed.
Syntax of a switch statement
Here’s the basic syntax of a switch statement in TypeScript:
let expr = 'value1'switch (expr) {case 'value1':// Code to execute if expr matches 'value1'breakcase 'value2':// Code to execute if expr matches 'value2'breakdefault:// Code to execute if expr matches none of the above}
- expr: This is the expression that is evaluated once at the start of the switch statement.
- case 'value': Each case label is tested against the value of
expr
. - break: This keyword stops the execution of more cases once a matching case is found. Without
break
, the switch will continue testing subsequent cases even if a match is found (known as "falling-through"). - default: This case is optional and executes if none of the specified cases match the expression.
Example of a switch case in TypeScript
Here's a practical example using a switch statement:
type Fruit = 'apple' | 'banana' | 'orange'function getFruitColor(fruit: Fruit): string {switch (fruit) {case 'apple':return 'red'case 'banana':return 'yellow'case 'orange':return 'orange'default:throw new Error('Unknown fruit')}}console.log(getFruitColor('apple')) // Outputs: red
Advanced usage: exhaustive checks in switch statements
TypeScript's type system allows for what is known as exhaustive checks in switch statements. An exhaustive check ensures that all possible cases are handled.
Using the never
type for exhaustive checks
The never
type in TypeScript is used for values that never occur. You can use it to ensure that every possible case in a union type is covered by a switch case. If not, TypeScript will throw a compilation error.
Here’s how you can implement an exhaustive check in a switch statement:
type Operation = 'create' | 'read' | 'update' | 'delete'function performOperation(op: Operation) {switch (op) {case 'create':// perform createbreakcase 'read':// perform readbreakcase 'update':// perform updatebreakcase 'delete':// perform deletebreakdefault:const exhaustiveCheck: never = opthrow new Error(`Unhandled case: ${exhaustiveCheck}`)}}
In the above example, if the Operation
type is extended later and the switch is not updated accordingly, TypeScript will signal an error because exhaustiveCheck
of type never
cannot be assigned a value.
Using exhaustive switch statements is particularly useful in applications with many distinct states or operations (like Redux reducers in front-end applications) where handling every possible case is important for maintaining a correct application state.
For further reading on TypeScript switch statements, see the official TypeScript documentation.