-
-
Notifications
You must be signed in to change notification settings - Fork 162
Description
Describe the bug
Do we see any issue with the first match below, or no? Another reported issue followed up with .otherwise; but - in my case - we use .exhaustive and end up throwing this error at runtime:
Error: Pattern matching error: no pattern matches value {}
Curiously, though, there is no compile-time type error as you'd usually expect to be coming from .exhaustive.
Thinking this may be caused by using a tagged union type with a partial tag (meaning one of the unioned types has an optional tagging property). The match..with..exhaustive expression seems to be fine with { type: undefined } but then throws at runtime. Only when swapping to { type: P.optional(undefined) } does the runtime error subside; but the main issue is that .exhaustive does not seem to be checking for this edge case.
import { match, P } from 'ts-pattern'
// a tagged union where `type` serves as the tag but is optional for the "default" type.
type One = {
// default
type?: 'one';
};
type Two = {
type: 'two';
};
type Thing = One | Two;
const thing: Thing = {};
function iThrow(thing: Thing): Thing['type'] {
return match(thing)
.with({ type: 'one' }, () => 'one' as const)
.with({ type: 'two' }, () => 'two' as const)
// will throw at runtime without a compile-time error
.with({ type: undefined }, () => undefined)
.exhaustive();
}
function imOk(thing: Thing): Thing['type'] {
return match(thing)
.with({ type: 'one' }, () => 'one' as const)
.with({ type: 'two' }, () => 'two' as const)
.with({ type: P.optional(undefined) }, () => undefined)
.exhaustive();
}
console.log(iThrow(thing));
console.log(imOk(thing));As another data point, if we change the types like so:
type One = {
// default
type?: undefined;
};
type Two = {
type: undefined;
};There is an .exhaustive error in that case.
Really appreciate this library. If this seems simple enough for a public contributor to assist with in some capacity, let me know.
Versions
- TypeScript version: 5.4.5
- ts-pattern version: 5.1.1
- environment: Chrome 128.0.6613.114