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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
export function exactlyOne<T>(
input: ReadonlyArray<T>,
property: string,
extraDescription: string = ''
): T {
if (input.length !== 1) {
throw new Error(
`Expected exactly one ${property} element, got ${input.length}. ${extraDescription}`
);
}
return input[0];
}
export function optionalOne<T>(
input: ReadonlyArray<T>,
property: string,
extraDescription: string = ''
): T | undefined {
if (input.length > 1) {
throw new Error(
`Expected one optional ${property} element, got ${input.length}. ${extraDescription}`
);
}
return input[0];
}
export function required<T>(
input: T | undefined,
property: string,
extraDescription: string = ''
): NonNullable<T> {
if (input == null) {
throw new Error(
`Expected a value for ${property}, got undefined. ${extraDescription}`
);
}
return input;
}
export function allRequired<T>(
input: ReadonlyArray<T | undefined>,
property: string,
extraDescription: string = ''
): Array<NonNullable<T>> {
return input.map((v, i) =>
required(v, `${property}[${i}]`, extraDescription)
);
}
export function atLeastOne<T>(
input: ReadonlyArray<T>,
property: string,
extraDescription: string = ''
): ReadonlyArray<T> {
if (input.length === 0) {
throw new Error(
`Expected at least one ${property} element. ${extraDescription}`
);
}
return input;
}
export function atLeastOneAndAllRequired<T>(
input: ReadonlyArray<T | undefined>,
property: string,
extraDescription: string = ''
): ReadonlyArray<NonNullable<T>> {
return atLeastOne(
allRequired(input, property, extraDescription),
property,
extraDescription
);
}
export function valueForKey<T>(
input: Record<string, T>,
key: string,
extraDescription: string = ''
): T {
return required(input[key], key, extraDescription);
}
export function valuesForKeys<T>(
input: Record<string, T>,
keys: string[],
extraDescription: string = ''
): T[] {
return keys.map((key) => valueForKey(input, key, extraDescription));
}
|