-
Notifications
You must be signed in to change notification settings - Fork 5
/
tuple.ts
78 lines (69 loc) · 1.98 KB
/
tuple.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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import {
createFail,
failSymbol,
InternalRuntype,
setupInternalRuntype,
isFail,
propagateFail,
Runtype,
} from './runtype'
import { arrayRuntype } from './array'
// TODO: find a simple (not type-computationally expensive) generic tuple definition.
// atm the one that comes closest would be: https://github.com/Microsoft/TypeScript/issues/13298#issuecomment-675386981
// For now, keep the tuple definition simple as I don't see a usecase for big
// (>5elements) tuples. Most of the time I use them only for simple [lat, lon],
// [x,y,z] and other vectors.
/**
* A tuple.
*/
export function tuple<A>(a: Runtype<A>): Runtype<[A]>
export function tuple<A, B>(a: Runtype<A>, b: Runtype<B>): Runtype<[A, B]>
export function tuple<A, B, C>(
a: Runtype<A>,
b: Runtype<B>,
c: Runtype<C>,
): Runtype<[A, B, C]>
export function tuple<A, B, C, D>(
a: Runtype<A>,
b: Runtype<B>,
c: Runtype<C>,
d: Runtype<D>,
): Runtype<[A, B, C, D]>
export function tuple<A, B, C, D, E>(
a: Runtype<A>,
b: Runtype<B>,
c: Runtype<C>,
d: Runtype<D>,
e: Runtype<E>,
): Runtype<[A, B, C, D, E]>
export function tuple(...types: Runtype<any>[]): Runtype<any> {
const itypes = types as InternalRuntype<any>[]
const isPure = itypes.every((t) => t.meta?.isPure)
return setupInternalRuntype<any>(
(v, failOrThrow) => {
const a = (arrayRuntype as InternalRuntype<any>)(v, failOrThrow)
if (isFail(a)) {
return propagateFail(failOrThrow, a, v)
}
if (a.length !== types.length) {
return createFail(
failOrThrow,
'tuple array does not have the required length',
v,
)
}
const res: any[] = isPure ? a : new Array(a.length)
for (let i = 0; i < types.length; i++) {
const item = itypes[i](a[i], failSymbol)
if (isFail(item)) {
return propagateFail(failOrThrow, item, v, i)
}
if (!isPure) {
res[i] = item
}
}
return res
},
{ isPure },
)
}