From fd8b8797dfc9481a2ad0eb6cdb1975ba1bc38c6e Mon Sep 17 00:00:00 2001 From: whilenot Date: Wed, 1 Jul 2026 11:37:04 +0200 Subject: [PATCH 1/2] Exhaustiveness checking with runtime error and assertNever --- .../copy/en/handbook-v2/Narrowing.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/documentation/copy/en/handbook-v2/Narrowing.md b/packages/documentation/copy/en/handbook-v2/Narrowing.md index c7a552ecf9b9..612944c7b072 100644 --- a/packages/documentation/copy/en/handbook-v2/Narrowing.md +++ b/packages/documentation/copy/en/handbook-v2/Narrowing.md @@ -708,9 +708,9 @@ In those cases, TypeScript will use a `never` type to represent a state which sh # Exhaustiveness checking -The `never` type is assignable to every type; however, no type is assignable to `never` (except `never` itself). This means you can use narrowing and rely on `never` turning up to do exhaustive checking in a `switch` statement. +The `never` type is assignable to every type; however, no type is assignable to `never` (except `never` itself). It is good practice to create a `assertNever` helper function that would raise a runtime error when called. This means you can use narrowing and rely on `never` turning up to do exhaustive checking in a `switch` statement. -For example, adding a `default` to our `getArea` function which tries to assign the shape to `never` will not raise an error when every possible case has been handled. +For example, adding a `default` to our `getArea` function which tries to call our `assertNever` function that expects shape to be `never` will not raise an error when every possible case has been handled. ```ts twoslash interface Circle { @@ -732,10 +732,13 @@ function getArea(shape: Shape) { case "square": return shape.sideLength ** 2; default: - const _exhaustiveCheck: never = shape; - return _exhaustiveCheck; + assertNever(shape); } } + +function assertNever(value: never) { + throw new Error(`Missing case for value: ${value}`); +} ``` Adding a new member to the `Shape` union, will cause a TypeScript error: @@ -766,8 +769,11 @@ function getArea(shape: Shape) { case "square": return shape.sideLength ** 2; default: - const _exhaustiveCheck: never = shape; - return _exhaustiveCheck; + assertNever(shape); } } + +function assertNever(value: never) { + throw new Error(`Missing case for value: ${value}`); +} ``` From acb8701c2b1ef3098c06c7e714dcbb6cbb9e7663 Mon Sep 17 00:00:00 2001 From: whilenot Date: Thu, 2 Jul 2026 10:37:21 +0200 Subject: [PATCH 2/2] Never return on never assertion --- packages/documentation/copy/en/handbook-v2/Narrowing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/documentation/copy/en/handbook-v2/Narrowing.md b/packages/documentation/copy/en/handbook-v2/Narrowing.md index 612944c7b072..5dd774920ba0 100644 --- a/packages/documentation/copy/en/handbook-v2/Narrowing.md +++ b/packages/documentation/copy/en/handbook-v2/Narrowing.md @@ -736,7 +736,7 @@ function getArea(shape: Shape) { } } -function assertNever(value: never) { +function assertNever(value: never): never { throw new Error(`Missing case for value: ${value}`); } ``` @@ -773,7 +773,7 @@ function getArea(shape: Shape) { } } -function assertNever(value: never) { +function assertNever(value: never): never { throw new Error(`Missing case for value: ${value}`); } ```