-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.ts
More file actions
101 lines (91 loc) · 2.45 KB
/
index.ts
File metadata and controls
101 lines (91 loc) · 2.45 KB
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
/*
* @poppinss/object-builder
*
* (c) Poppinss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
type PickKeysByValue<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T]
type OmitProperties<T, P> = Omit<T, PickKeysByValue<T, P>>
/**
* A simple class to build an object incrementally. It is helpful when you
* want to add properties to the object conditionally.
*
* Instead of writing
* ```
* const obj = {
* ...(user.id ? { id: user.id } : {}),
* ...(user.firstName && user.lastName ? { name: `${user.firstName} ${user.lastName}` } : {}),
* }
* ```
*
* You can write
*
* const obj = new ObjectBuilder()
* .add('id', user.id)
* .add(
* 'fullName',
* user.firstName && user.lastName ? `${user.firstName} ${user.lastName}` : undefined
* )
* .toObject()
*/
export class ObjectBuilder<
ReturnType extends Record<string, any>,
IgnoreNull extends boolean = false,
> {
#ignoreNull: boolean
values: ReturnType
constructor(initialValue: ReturnType, ignoreNull?: IgnoreNull) {
this.values = initialValue
this.#ignoreNull = ignoreNull === true ? true : false
}
/**
* Add a key-value pair to the object
*
* - Undefined values are ignored
* - Null values are ignored, when `ignoreNull` is set to true
*/
add<Prop extends string>(key: Prop, value: undefined): this
add<Prop extends string, Value>(
key: Prop,
value: Value
): ObjectBuilder<ReturnType & { [P in Prop]: Value }, IgnoreNull>
add<Prop extends string, Value>(key: Prop, value: Value): this {
if (value === undefined) {
return this
}
if (this.#ignoreNull === true && value === null) {
return this
}
;(this.values as any)[key] = value
return this
}
/**
* Remove key from the object
*/
remove<K extends keyof ReturnType>(key: K): this {
delete this.values[key]
return this
}
/**
* Find if a value exists
*/
has<K extends keyof ReturnType>(key: K): boolean {
return this.get(key) !== undefined
}
/**
* Get the existing value for a given key
*/
get<K extends keyof ReturnType>(key: K): ReturnType[K] {
return this.values[key]
}
/**
* Get the underlying constructed object
*/
toObject(): IgnoreNull extends true
? { [K in keyof OmitProperties<ReturnType, null>]: ReturnType[K] }
: { [K in keyof ReturnType]: ReturnType[K] } {
return this.values
}
}