/
json.ts
73 lines (64 loc) · 2.03 KB
/
json.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
/**
* A single JSON value. This is the missing return type of JSON.parse().
*/
export type JsonCompatibleValue =
| JsonCompatibleDictionary
| JsonCompatibleArray
| string
| number
| boolean
| null;
/**
* An array of JsonCompatibleValue
*/
// Use interface extension instead of type alias to make circular declaration possible.
export interface JsonCompatibleArray extends ReadonlyArray<JsonCompatibleValue> {}
/**
* A string to json value dictionary.
*/
export interface JsonCompatibleDictionary {
readonly [key: string]: JsonCompatibleValue | readonly JsonCompatibleValue[];
}
export function isJsonCompatibleValue(value: unknown): value is JsonCompatibleValue {
if (
typeof value === "string" ||
typeof value === "number" ||
typeof value === "boolean" ||
value === null ||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
isJsonCompatibleArray(value) ||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
isJsonCompatibleDictionary(value)
) {
return true;
} else {
return false;
}
}
export function isJsonCompatibleArray(value: unknown): value is JsonCompatibleArray {
if (!Array.isArray(value)) {
return false;
}
for (const item of value) {
if (!isJsonCompatibleValue(item)) {
return false;
}
}
// all items okay
return true;
}
export function isJsonCompatibleDictionary(data: unknown): data is JsonCompatibleDictionary {
if (typeof data !== "object" || data === null) {
// data must be a non-null object
return false;
}
// Exclude special kind of objects like Array, Date or Uint8Array
// Object.prototype.toString() returns a specified value:
// http://www.ecma-international.org/ecma-262/7.0/index.html#sec-object.prototype.tostring
if (Object.prototype.toString.call(data) !== "[object Object]") {
return false;
}
// TODO: replace with Object.values when available (ES2017+)
const values = Object.getOwnPropertyNames(data).map(key => (data as any)[key]);
return values.every(isJsonCompatibleValue);
}