-
Notifications
You must be signed in to change notification settings - Fork 3
/
matcher.ts
58 lines (51 loc) · 1.5 KB
/
matcher.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import type { AnyAction } from "./types.ts";
type ActionType = string;
type GuardPredicate<G extends T, T = unknown> = (arg: T) => arg is G;
type Predicate<Guard extends AnyAction = AnyAction> = (
action: Guard,
) => boolean;
type StringableActionCreator<A extends AnyAction = AnyAction> = {
(...args: unknown[]): A;
toString(): string;
};
type SubPattern<Guard extends AnyAction = AnyAction> =
| Predicate<Guard>
| StringableActionCreator
| ActionType;
export type Pattern = SubPattern | SubPattern[];
type ActionSubPattern<Guard extends AnyAction = AnyAction> =
| GuardPredicate<Guard, AnyAction>
| StringableActionCreator<Guard>
| Predicate<Guard>
| ActionType;
export type ActionPattern<Guard extends AnyAction = AnyAction> =
| ActionSubPattern<Guard>
| ActionSubPattern<Guard>[];
export function matcher(pattern: ActionPattern): Predicate {
if (pattern === "*") {
return function (input) {
return !!input;
};
}
if (typeof pattern === "string") {
return function (input) {
return pattern === input.type;
};
}
if (Array.isArray(pattern)) {
return function (input) {
return pattern.some((p) => matcher(p)(input));
};
}
if (typeof pattern === "function" && Object.hasOwn(pattern, "toString")) {
return function (input) {
return pattern.toString() === input.type;
};
}
if (typeof pattern === "function") {
return function (input) {
return pattern(input) as boolean;
};
}
throw new Error("invalid pattern");
}