diff --git a/README.md b/README.md index 560f00b0..82385edd 100644 --- a/README.md +++ b/README.md @@ -561,12 +561,36 @@ match(...) .exhaustive() ``` -Runs the pattern-matching expression and returns its result. It also enables exhaustiveness checking, making sure at compile time that we have handled all possible cases. +Runs the pattern-matching expression and returns its result. It also enables exhaustiveness checking, making sure that we have handled all possible cases **at compile time**. + +By default, `.exhaustive()` will throw an error if the input value wasn't handled by any `.with(...)` clause. This should only happen if your types are incorrect. + +It is possible to pass your own handler function as a parameter to decide what should happen if an unexpected value has been received. You can for example throw your own custom error: + +```ts +match(...) + .with(...) + .exhaustive((unexpected: unknown) => { + throw MyCustomError(unexpected); + }) +``` + +Or log an error and return a default value: + +```ts +match(...) + .with(P.string, (str) => str.length) + .exhaustive((notAString: unknown) => { + console.log(`received an unexpected value: ${notAString}`); + return 0; + }) +``` #### Signature ```ts function exhaustive(): TOutput; +function exhaustive(handler: (unexpectedValue: unknown) => TOutput): TOutput; ``` #### Example diff --git a/src/match.ts b/src/match.ts index 775019db..5785111c 100644 --- a/src/match.ts +++ b/src/match.ts @@ -111,9 +111,9 @@ class MatchExpression { return handler(this.input); } - exhaustive(catcher = defaultCatcher): output { + exhaustive(unexpectedValueHandler = defaultCatcher): output { if (this.state.matched) return this.state.value; - return catcher(this.input); + return unexpectedValueHandler(this.input); } run(): output { diff --git a/src/types/Match.ts b/src/types/Match.ts index de19f1e6..47d7dea5 100644 --- a/src/types/Match.ts +++ b/src/types/Match.ts @@ -250,6 +250,6 @@ type MakeTuples = { type Exhaustive = { (): PickReturnValue; ( - handler: (unmatchedValue: unknown) => PickReturnValue + handler: (unexpectedValue: unknown) => PickReturnValue ): PickReturnValue>; }; diff --git a/tests/exhaustive-fallback.test.ts b/tests/exhaustive-fallback.test.ts index dc5c76e3..e824d464 100644 --- a/tests/exhaustive-fallback.test.ts +++ b/tests/exhaustive-fallback.test.ts @@ -9,7 +9,6 @@ describe('Exhaustive fallback function', () => { .with('b', (x) => x) .exhaustive((v) => ({ unexpectedValue: v })); - // check return type type t = Expect< Equal >; @@ -33,7 +32,10 @@ describe('Exhaustive fallback function', () => { .with('a', (x) => x) .with('b', (x) => x) // @ts-expect-error 'c' isn't assignable to a|b - .exhaustive(() => 'c'); + .exhaustive(() => { + // Note: ideally the error message should be here. + return 'c'; + }); }); it('should return a value assignable .returnType()', () => {