-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
128 lines (113 loc) · 3.17 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
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
* Remove all properties from T that are assignable to U
*/
export type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
/**
* Exclusive OR between two types
*/
export type TypeXOR<T, U> = (T | U) extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;
/**
* JavaScript falsy types
*/
export type Falsy = undefined | null | false | 0 | '';
/**
* JavaScript primitive types accepted as index signatures
*/
export type PrimitiveValidIndexSignature = string | number | symbol;
/**
* JavaScript primitive non-falsy types
*/
export type Primitive = PrimitiveValidIndexSignature | boolean;
/**
* JavaScript non-falsy types
*/
export type Complex = Primitive | Array<Primitive> | {
[k: PrimitiveValidIndexSignature]: Complex
} | Date;
/**
* JavaScript primitive types, including falsy values
*/
export type FalsyOrLiteral = Falsy | Primitive;
/**
* An object made of string keys and non-falsy values. To add new types to values, use the `T` type parameter
* @template T?=Complex
*/
export type Document<T = Complex> = Record<string, Complex | T>;
/**
* A JSON, as a string or as a parsed object or array
*/
export type JsonOrString = Document | Document[] | string;
/**
* A generic tree
*/
export type TreeItem<T> = T & { children: TreeItem<T>[] };
/**
* A type that implements a constructor without arguments
*/
export interface EmptyConstructorOf<T> {
new(): T;
}
/**
* A type that is clonable: it can be instantiated with a partial object
* @export
* @class ClonableType
* @template T
*/
export class ClonableType<T> {
/**
* Creates an instance of ClonableType with a partial object to be copied.
* @param {Partial<T>} [obj]
* @memberof ClonableType
*/
constructor(obj?: Partial<T>) {
if (obj) Object.assign(this, obj);
}
}
/**
* Check if a value is falsy or a string with only spaces, ignoring number 0
* @returns boolean
*/
export const isFalsyOrSpaces = (i: FalsyOrLiteral) => {
if (typeof i === 'number' && i === 0) return false;
return ((typeof i === 'string' && i.trim() === '') || (!i));
};
/**
* Clones an object, optionally removing a list of properties
* @export
* @template T
* @template K
* @param {T} obj The object to clone
* @param {...K[]} props The properties to remove
* @return {*} {Omit<T, K>}
*/
export function withoutProps
<T extends Document, K extends keyof T>(
obj: T,
...props: K[]
): Omit<T, K> {
const { ...rest } = obj;
props.forEach(prop => {
delete rest[prop];
});
return rest;
}
/**
* Checks if two objects are equal using the `equals` method or strict equality
*/
export function equals(a: any, b: any): boolean {
return (a === b) || (typeof a.equals === 'function' && a.equals(b));
}
/**
* List all methods of an object and its prototypes
*/
export function getMethods(obj): string[] {
const properties = new Set<PrimitiveValidIndexSignature>();
let currentObj = obj;
do {
Object.getOwnPropertyNames(currentObj).map(item => properties.add(item));
// eslint-disable-next-line no-cond-assign
} while ((currentObj = Object.getPrototypeOf(currentObj)));
return [...properties.keys()]
.filter(item => typeof obj[item] === 'function')
.map(i => i.toString());
}