The never Type and assertNever Pattern
When working with discriminated unions in TypeScript, it is essential to ensure that every possible variant is handled in your logic. The never type and the assertNever pattern are powerful tools for enforcing exhaustive checks, especially in switch statements. By leveraging these, you can catch missing cases at compile time, preventing subtle bugs that might otherwise appear when new variants are added to a union type. This practice is especially important for code maintainability and safety as your codebase grows.
123456789101112131415161718type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number }; function assertNever(x: never): never { throw new Error("Unexpected object: " + x); } function area(shape: Shape): number { switch (shape.kind) { case "circle": return Math.PI * shape.radius * shape.radius; case "square": return shape.side * shape.side; default: return assertNever(shape); // Compile-time error if a new kind is added and not handled } }
In this example, the assertNever function takes a parameter of type never. If the switch statement is missing a case for a new variant of the Shape union, TypeScript will flag a compile-time error at the call to assertNever. This ensures that all possible variants are considered, making it much less likely to overlook a case when the union is extended. Exhaustive checking using never and assertNever is critical for maintainability because it forces you to update all relevant logic whenever your union types evolve, reducing the risk of runtime errors caused by unhandled cases.
Merci pour vos commentaires !
Demandez à l'IA
Demandez à l'IA
Posez n'importe quelle question ou essayez l'une des questions suggérées pour commencer notre discussion
Can you explain how the `never` type works in TypeScript?
What happens if I add a new shape to the `Shape` union?
Why is exhaustive checking important in large codebases?
Awesome!
Completion rate improved to 5.88
The never Type and assertNever Pattern
Glissez pour afficher le menu
When working with discriminated unions in TypeScript, it is essential to ensure that every possible variant is handled in your logic. The never type and the assertNever pattern are powerful tools for enforcing exhaustive checks, especially in switch statements. By leveraging these, you can catch missing cases at compile time, preventing subtle bugs that might otherwise appear when new variants are added to a union type. This practice is especially important for code maintainability and safety as your codebase grows.
123456789101112131415161718type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number }; function assertNever(x: never): never { throw new Error("Unexpected object: " + x); } function area(shape: Shape): number { switch (shape.kind) { case "circle": return Math.PI * shape.radius * shape.radius; case "square": return shape.side * shape.side; default: return assertNever(shape); // Compile-time error if a new kind is added and not handled } }
In this example, the assertNever function takes a parameter of type never. If the switch statement is missing a case for a new variant of the Shape union, TypeScript will flag a compile-time error at the call to assertNever. This ensures that all possible variants are considered, making it much less likely to overlook a case when the union is extended. Exhaustive checking using never and assertNever is critical for maintainability because it forces you to update all relevant logic whenever your union types evolve, reducing the risk of runtime errors caused by unhandled cases.
Merci pour vos commentaires !