-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
44 lines (41 loc) · 1.11 KB
/
index.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
import Guard, { GuardedType } from "../../Guard";
import TValidate from "../TValidate";
/**
* Validates if at least one type criteria is met.
*
* @returns
* A `Guard` that is similar in concept as the `|` operator in TypeScript.
* Accepts a value when it was accepted by at least one of the `guards`.
*
* `guard.name: "<typeA> | <typeB>"`
*
* @example
* ```ts
* const guard = TOr(TNumber, TString);
* guard.isValid(1); // true
* guard.isValid("foo"); // true
* guard.isValid(true); // false
* guard.name === "number | string"; // true
* ```
*/
export default function TOr<A, B, T extends Array<Guard<unknown>>>(
guardA: Guard<A>,
guardB: Guard<B>,
...others: T
): Guard<A | B | GuardedType<ArrayType<T>>> {
const guards = [guardA, guardB, ...others];
return TValidate<A | B | GuardedType<ArrayType<T>>>(
`(${guards.map(({ name }) => name).join(" | ")})`,
(value) => {
{
for (const guard of guards) {
if (guard.isValid(value)) return true;
}
return false;
}
}
);
}
type ArrayType<C extends Array<unknown>> = C extends Array<infer T>
? T
: unknown;