| 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 |
4x
126x
4x
4x
26x
23x
193x
197x
14x
183x
183x
11x
42x
34x
13x
12x
22x
11x
21x
12x
11x
4x
78x
69x
67x
67x
67x
54x
| import { values, isList, isObject, createEnumFactory } from './utils';
// Tiny ArgLessEnum to bypass the circular dependency shithole
const ArgLessEnum = createEnumFactory({
createConstructor: (Type, constr) => (...args) => ({ ...constr, args }),
});
// type Type = Type|String;
// Cant use Type to define Type so ArgLessEnum
const Type = ArgLessEnum([
'Any',
'String',
'Number',
'Bool',
'List',
'Map',
'Record',
'Func',
'Enum',
'OneOf',
]);
// validateList :: (Type, [a]) -> Boolean
const validateList = (innerType, list) =>
isList(list) && (
(innerType && list.length > 0)
? list.length === [...list].filter(isOfType(innerType)).length
: true
);
// validateRecord :: Object Type -> Object a -> Boolean
export const validateRecord = (shape, obj) => validateArgs(values(shape), values(obj));
// isOfType :: Type -> a -> Boolean
export const isOfType = type => value => {
// Dynamic argument description
if(typeof type === 'string' && value !== undefined)
return true;
Eif (Type.isConstructor(type)) {
return !!Type.match(type, {
Any: () => true,
String: () => typeof value === 'string',
Number: () => typeof value === 'number',
Bool: () => typeof value === 'boolean',
Func: () => typeof value === 'function',
List: innerType => validateList(innerType, value),
Map: innerType => innerType && isObject(value) && validateList(innerType, values(value)),
Record: shape => isObject(value) && (shape ? validateRecord(shape, value) : true),
OneOf: typeList => !![...typeList].filter(type => isOfType(type)(value)).length,
Enum: InnerType => value && InnerType.isConstructor(value),
});
}
return false;
};
// validateArgs :: ([Type], [a]) -> Bool
export const validateArgs = (typeList, valueList) => {
if(typeList.length !== valueList.length) return false;
if(typeList.length === 0) return true;
const [type, ...types] = typeList;
const [val, ...vals] = valueList;
if(!isOfType(type)(val)) return false;
return types.length > 0 ? validateArgs(types, vals) : true;
};
export default Type;
|