Skip to content

Commit

Permalink
feat(match): merge With and WithChecker
Browse files Browse the repository at this point in the history
  • Loading branch information
ecyrbe committed Aug 1, 2023
1 parent ac50c84 commit f6c7c16
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 18 deletions.
52 changes: 44 additions & 8 deletions src/internals/match/Match.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import * as Impl from "./impl/match";
* @example
* ```ts
* type Test<T> = Match<T, [
* With<{ msg: Match.arg0 }, S.Prepend<"Message: ">>,
* WithExact<number, string>,
* With<string, S.Append<": string">>,
* With<any, F.Constant<"default value">>
* Match.With<number, "can be a type number or a value N that is a number">>,
* Match.With<{ msg: Match.arg0<string> }, "can be a type { msg: string } or any actual string value { msg: "hello" } and extracts arg0">>,
* Match.With<IsComplexCheck, "can check for complex types like unions, intersections, tuples, etc.">,
* Match.WithEqual<{ msg: string }, "is exactly { msg: string } and will not match { msg: "hello" }">,
* Match.WithPredicate<Equal, string, "is exactly string">,
* Match.With<any, "default value">
* ]>
* ```
*/
Expand All @@ -39,13 +41,47 @@ interface PatternMatchFn extends Fn {
return: this["arg0"] extends Impl.ReplaceArgsWithConstraint<this["arg1"]> ? true : false;
}

interface ExactMatchFn extends Fn {
interface EqualMatchFn extends Fn {
return: Equal<this["arg0"], this["arg1"]>;
}

export namespace Match {
export type With<pattern, handler> = Impl.With<pattern, handler, PatternMatchFn>;
export type WithExact<pattern, handler> = Impl.With<pattern, handler, ExactMatchFn>;
/**
* Match.With matches a pattern or type checker with a handler.
* The pattern can be a type or a type checker that returns true or false and takes one parameter.
* The handler can be any Fn or value type.
* @example
* ```ts
* type Test<T> = Match<T, [
* Match.With<number, "can be a type number or a value N that is a number">>,
* Match.With<{ msg: Match.arg0<string> }, "can be a type { msg: string } or any actual string value { msg: "hello" } and extracts arg0">>,
* Match.With<IsComplexCheck, "can check for complex types like unions, intersections, tuples, etc.">,
* ]>
* ```
*/
export type With<pattern, handler> = pattern extends Fn ? Impl.With<never, handler, pattern> : Impl.With<pattern, handler, PatternMatchFn>;

Check failure on line 62 in src/internals/match/Match.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

Type 'Fn & pattern' does not satisfy the constraint 'Fn'.
/**
* Match.WithEqual matches exactly a type with a handler.
* The handler can be any Fn or value type.
* @example
* ```ts
* type Test<T> = Match<T, [
* Match.WithEqual<{ msg: string }, "is exactly { msg: string } and will not match { msg: "hello" }">,
* ]>
* ```
*/
export type WithEqual<pattern, handler> = Impl.With<pattern, handler, EqualMatchFn>;
/**
* Match.WithPredicate matches a predicate Fn with a handler.
* The predicate Fn must return true or false and take two parameters.
* The handler can be any Fn or value type.
* @example
* ```ts
* type Test<T> = Match<T, [
* Match.WithPredicate<Equal, string, "is exactly string">,
* Match.WithPredicate<Extend, { msg: string }, "is a subtype of { msg: string } and will match { msg: "hello" }">,
* ]>
* ```
*/
export type WithPredicate<predicate extends Fn, pattern, handler> = Impl.With<pattern, handler, predicate>;
export type WithChecker<checker extends Fn, handler> = Impl.With<never, handler, checker>;
}
20 changes: 10 additions & 10 deletions test/match.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ describe("Match", () => {
Match<
T,
[
Match.WithExact<{ msg: string }, Constant<"string">>,
Match.WithExact<{ msg: string; x: number }, Constant<"string + x">>,
Match.WithExact<{ msg: string; x: number; y: boolean }, Constant<"all">>,
Match.With<any, Constant<"don't match strictly with the provided types">>
Match.WithEqual<{ msg: string }, "string">,
Match.WithEqual<{ msg: string; x: number }, "string + x">,
Match.WithEqual<{ msg: string; x: number; y: boolean }, "all">,
Match.With<any, "don't match strictly with the provided types">
]
>
>;
Expand Down Expand Up @@ -151,9 +151,9 @@ describe("Match", () => {
Match<
T,
[
Match.WithPredicate<TestPredicate, string, Constant<"string">>,
Match.WithPredicate<TestPredicate, number, Constant<"number">>,
Match.WithPredicate<TestPredicate, boolean, Constant<"boolean">>,
Match.WithPredicate<TestPredicate, string, "string">,
Match.WithPredicate<TestPredicate, number, "number">,
Match.WithPredicate<TestPredicate, boolean, "boolean">,
]
>
>;
Expand Down Expand Up @@ -200,9 +200,9 @@ describe("Match", () => {
Match<
T,
[
Match.WithChecker<TestStringChecker, Constant<"string">>,
Match.WithChecker<TestNumberChecker, Constant<"number">>,
Match.WithChecker<TestBooleanChecker, Constant<"boolean">>,
Match.With<TestStringChecker, "string">,
Match.With<TestNumberChecker, "number">,
Match.With<TestBooleanChecker, "boolean">,
]
>
>;
Expand Down

0 comments on commit f6c7c16

Please sign in to comment.