-
-
Notifications
You must be signed in to change notification settings - Fork 159
Description
Describe the bug
When using ts-pattern with a branded primitive type (e.g., string & { __type: 'id' }), calling .exhaustive() does not trigger a TypeScript error or a runtime error, even if not all possible inputs are handled.
This gives a false sense of exhaustiveness. The pattern only matches one literal value, but ts-pattern doesn’t detect that other values (with the same brand) are possible. At runtime, unmatched values simply fall through silently, despite .exhaustive() being used.
TypeScript playground with a minimal reproduction case
👉 [Playground Link](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAbziAhjAxgCwDRwApwC+cAZlBCHAOQwDOAtGGjAKZQB2VAUFzAJ5gWcAEZQU7ACYsJASQlwAvHFowowdgHM4AMkRwA+vv6CAXHABEwCeaIBuHugjsVcK4osBGAEwBmGyloRMUlpOXsSAFd2dBhgJzhWFQAKdTAImDNRcSlZCQBKRC44YrgoFhgIjmQ0LBT2NJg8opKAOgB3YBhMFIlcJIKFAD44R2cIABsWFvGIDSSqFnB+OHHgFSo8ppK4AHod13gQCJcNYAA3IRAhNnIoODbMYEm4GTgUSnYIeExslnG38b-dABFi0ZrFFosAAeP2OsQu-XshAcTloEymMzm5m8PgALP5AlkQrk8rYgA)
Code from playground:
import { match } from 'ts-pattern';
type BrandedId = string & { __type: 'id' };
const id = "123" as BrandedId;
function test(input: BrandedId) {
return match(input)
.with(id, () => "matched")
.exhaustive(); // ❌ No TS error or runtime error
}
test("456" as BrandedId); // ❌ Compiles, but give me runtime error.Expected behavior
- At compile time: TypeScript should warn that the match is not exhaustive (e.g., missing fallback or additional cases).
- At runtime:
.exhaustive()should throw if no pattern matches.
Versions
- TypeScript version: 5.8.3
- ts-pattern version: 5.7.0 (latest)