@planet-matrix/mobius-model 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +30 -1
  3. package/dist/index.js +4 -2
  4. package/dist/index.js.map +22 -4
  5. package/package.json +3 -3
  6. package/scripts/build.ts +4 -4
  7. package/src/basic/README.md +144 -0
  8. package/src/basic/array.ts +872 -0
  9. package/src/basic/bigint.ts +114 -0
  10. package/src/basic/boolean.ts +180 -0
  11. package/src/basic/enhance.ts +10 -0
  12. package/src/basic/error.ts +51 -0
  13. package/src/basic/function.ts +453 -0
  14. package/src/basic/helper.ts +276 -0
  15. package/src/basic/index.ts +17 -0
  16. package/src/basic/is.ts +320 -0
  17. package/src/basic/number.ts +178 -0
  18. package/src/basic/object.ts +140 -0
  19. package/src/basic/promise.ts +464 -0
  20. package/src/basic/regexp.ts +7 -0
  21. package/src/basic/stream.ts +140 -0
  22. package/src/basic/string.ts +308 -0
  23. package/src/basic/symbol.ts +164 -0
  24. package/src/basic/temporal.ts +224 -0
  25. package/src/encoding/README.md +105 -0
  26. package/src/encoding/base64.ts +98 -0
  27. package/src/encoding/index.ts +1 -0
  28. package/src/index.ts +4 -0
  29. package/src/random/README.md +109 -0
  30. package/src/random/index.ts +1 -0
  31. package/src/random/uuid.ts +103 -0
  32. package/src/type/README.md +330 -0
  33. package/src/type/array.ts +5 -0
  34. package/src/type/boolean.ts +471 -0
  35. package/src/type/class.ts +419 -0
  36. package/src/type/function.ts +1519 -0
  37. package/src/type/helper.ts +135 -0
  38. package/src/type/index.ts +14 -0
  39. package/src/type/intersection.ts +93 -0
  40. package/src/type/is.ts +247 -0
  41. package/src/type/iteration.ts +233 -0
  42. package/src/type/number.ts +732 -0
  43. package/src/type/object.ts +788 -0
  44. package/src/type/path.ts +73 -0
  45. package/src/type/string.ts +1004 -0
  46. package/src/type/tuple.ts +2424 -0
  47. package/src/type/union.ts +108 -0
  48. package/tests/unit/basic/array.spec.ts +290 -0
  49. package/tests/unit/basic/bigint.spec.ts +50 -0
  50. package/tests/unit/basic/boolean.spec.ts +74 -0
  51. package/tests/unit/basic/error.spec.ts +32 -0
  52. package/tests/unit/basic/function.spec.ts +175 -0
  53. package/tests/unit/basic/helper.spec.ts +118 -0
  54. package/tests/unit/basic/number.spec.ts +74 -0
  55. package/tests/unit/basic/object.spec.ts +46 -0
  56. package/tests/unit/basic/promise.spec.ts +232 -0
  57. package/tests/unit/basic/regexp.spec.ts +11 -0
  58. package/tests/unit/basic/stream.spec.ts +120 -0
  59. package/tests/unit/basic/string.spec.ts +74 -0
  60. package/tests/unit/basic/symbol.spec.ts +72 -0
  61. package/tests/unit/basic/temporal.spec.ts +78 -0
  62. package/tests/unit/encoding/base64.spec.ts +40 -0
  63. package/tests/unit/random/uuid.spec.ts +37 -0
  64. package/dist/index.d.ts +0 -2
  65. package/dist/index.d.ts.map +0 -1
  66. package/dist/reactor/index.d.ts +0 -3
  67. package/dist/reactor/index.d.ts.map +0 -1
  68. package/dist/reactor/reactor-core/flags.d.ts +0 -99
  69. package/dist/reactor/reactor-core/flags.d.ts.map +0 -1
  70. package/dist/reactor/reactor-core/index.d.ts +0 -4
  71. package/dist/reactor/reactor-core/index.d.ts.map +0 -1
  72. package/dist/reactor/reactor-core/primitive.d.ts +0 -276
  73. package/dist/reactor/reactor-core/primitive.d.ts.map +0 -1
  74. package/dist/reactor/reactor-core/reactive-system.d.ts +0 -241
  75. package/dist/reactor/reactor-core/reactive-system.d.ts.map +0 -1
  76. package/dist/reactor/reactor-operators/branch.d.ts +0 -19
  77. package/dist/reactor/reactor-operators/branch.d.ts.map +0 -1
  78. package/dist/reactor/reactor-operators/convert.d.ts +0 -30
  79. package/dist/reactor/reactor-operators/convert.d.ts.map +0 -1
  80. package/dist/reactor/reactor-operators/create.d.ts +0 -26
  81. package/dist/reactor/reactor-operators/create.d.ts.map +0 -1
  82. package/dist/reactor/reactor-operators/filter.d.ts +0 -269
  83. package/dist/reactor/reactor-operators/filter.d.ts.map +0 -1
  84. package/dist/reactor/reactor-operators/index.d.ts +0 -8
  85. package/dist/reactor/reactor-operators/index.d.ts.map +0 -1
  86. package/dist/reactor/reactor-operators/join.d.ts +0 -48
  87. package/dist/reactor/reactor-operators/join.d.ts.map +0 -1
  88. package/dist/reactor/reactor-operators/map.d.ts +0 -165
  89. package/dist/reactor/reactor-operators/map.d.ts.map +0 -1
  90. package/dist/reactor/reactor-operators/utility.d.ts +0 -48
  91. package/dist/reactor/reactor-operators/utility.d.ts.map +0 -1
@@ -0,0 +1,788 @@
1
+ // oxlint-disable no-empty-object-type
2
+ // oxlint-disable no-unsafe-function-type
3
+ // oxlint-disable ban-types
4
+ // oxlint-disable no-explicit-any
5
+
6
+ import type {
7
+ Nilable,
8
+ NonNilable,
9
+ NonNullable,
10
+ NonUndefinedable,
11
+ Nullable,
12
+ Undefinedable,
13
+ } from "./is.ts"
14
+ import type { UnionComplement, UnionDifference, UnionIntersection } from "./union.ts"
15
+
16
+ // ============================================================================
17
+ // Primitives
18
+ // ============================================================================
19
+
20
+ /**
21
+ * Strict version of `Omit`, `K` must be subset of `typeof T`.
22
+ */
23
+ export type StrictOmit<T, K extends keyof T> = Omit<T, K>
24
+
25
+ export type StringRecord<T> = Record<string, T>
26
+ export type NumberRecord<T> = Record<number, T>
27
+ export type SymbolRecord<T> = Record<symbol, T>
28
+ export type HybridRecord<T> = Record<string | number | symbol, T>
29
+ export type AnyStringRecord = StringRecord<any>
30
+ export type AnyNumberRecord = NumberRecord<any>
31
+ export type AnySymbolRecord = SymbolRecord<any>
32
+ export type AnyHybridRecord = Record<string | number | symbol, any>
33
+ export type AnyRecord = AnyStringRecord | AnyNumberRecord | AnySymbolRecord
34
+
35
+ export type ObjectExact<A extends object> = A & { __brand: keyof A };
36
+
37
+ /**
38
+ * @see {@link https://stackoverflow.com/questions/78453542/intersection-with-object-in-prettify-helper-type}
39
+ * @see {@link https://github.com/mylesmmurphy/prettify-ts}
40
+ */
41
+ export type ObjectPrettify<Target extends AnyHybridRecord> = Pick<Target, keyof Target>
42
+ export type ObjectPrettify2<Target extends AnyHybridRecord> = Target extends infer O ? { [K in keyof O]: O[K] } : never
43
+
44
+ // ============================================================================
45
+ // Validation
46
+ // ============================================================================
47
+
48
+ /**
49
+ * If the `Target` is an empty Record/Object, then return `true`.
50
+ *
51
+ * @example
52
+ * ```
53
+ * // Expect: true
54
+ * type Example1 = ObjectIsEmpty<{}>
55
+ * // Expect: false
56
+ * type Example2 = ObjectIsEmpty<{ a: number }>
57
+ * ```
58
+ */
59
+ export type ObjectIsEmpty<Target extends AnyStringRecord> = keyof Target extends never ? true : false
60
+
61
+ /**
62
+ * If the `Target` is an empty Record/Object, then return `never`.
63
+ *
64
+ * @see {@link https://github.com/ts-essentials/ts-essentials#nonemptyobject}
65
+ * @see {@link https://github.com/ts-essentials/ts-essentials/tree/master/lib/non-empty-object}
66
+ */
67
+ export type ObjectNonEmpty<Target extends AnyStringRecord> = keyof Target extends never ? never : Target
68
+
69
+ // ============================================================================
70
+ // Extraction
71
+ // ============================================================================
72
+
73
+ /**
74
+ * @example
75
+ * ```
76
+ * interface Props { name: string, age: number, visible: boolean }
77
+ * // Expect: 'name' | 'age' | 'visible'
78
+ * type Example1 = ObjectKeys<Props>
79
+ * ```
80
+ */
81
+ export type ObjectKeys<Target> = Target extends AnyHybridRecord ? keyof Target : never
82
+
83
+ /**
84
+ * @example
85
+ * ```
86
+ * interface Props { name: string, age: number, visible: boolean }
87
+ * // Expect: string | number | boolean
88
+ * type Example1 = ObjectValues<Props>
89
+ * ```
90
+ */
91
+ export type ObjectValues<Target> = Target extends AnyHybridRecord ? Target[keyof Target] : never
92
+
93
+ /**
94
+ * @example
95
+ * ```
96
+ * type MixedProps = {name: string; setName: (name: string) => void; someKeys?: string; someFn?: (...args: any) => any;};
97
+ *
98
+ * // Expect: "setName | someFn"
99
+ * type Example1 = FunctionKeys<MixedProps>
100
+ * ```
101
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
102
+ */
103
+ export type FunctionKeys<Target extends AnyHybridRecord> = {
104
+ [Key in keyof Target]-?: NonUndefinedable<Target[Key]> extends Function ? Key : never;
105
+ }[keyof Target]
106
+ /**
107
+ * @example
108
+ * ```
109
+ * type MixedProps = {name: string; setName: (name: string) => void; someKeys?: string; someFn?: (...args: any) => any;};
110
+ *
111
+ * // Expect: "name | someKey"
112
+ * type Example1 = NonFunctionKeys<MixedProps>
113
+ * ```
114
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
115
+ */
116
+ export type NonFunctionKeys<Target extends AnyHybridRecord> = {
117
+ [Key in keyof Target]-?: NonUndefinedable<Target[Key]> extends Function ? never : Key;
118
+ }[keyof Target]
119
+
120
+ /**
121
+ * @see {@link https://github.com/ts-essentials/ts-essentials/blob/5aa1f264e77fb36bb3f673c49f00927c7c181a7f/lib/types.ts#L440 warning}
122
+ * @see {@link https://stackoverflow.com/a/52473108/1815209 explain with comments}
123
+ */
124
+ type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? A : B
125
+ /**
126
+ * @example
127
+ * ```
128
+ * type Props = { readonly foo: string; bar: number };
129
+ * // Expect: "foo"
130
+ * type Example1 = ReadonlyKeys<Props>
131
+ * ```
132
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
133
+ * @see {@link https://stackoverflow.com/questions/52443276/how-to-exclude-getter-only-properties-from-type-in-typescript}
134
+ */
135
+ export type ReadonlyKeys<Target extends AnyHybridRecord> = {
136
+ [Key in keyof Target]-?: IfEquals<{ [Q in Key]: Target[Key] }, { -readonly [Q in Key]: Target[Key] }, never, Key>
137
+ }[keyof Target]
138
+ /**
139
+ * @example
140
+ * ```
141
+ * interface Props { readonly foo: string, bar: number }
142
+ * // Expect: "bar"
143
+ * type Example1 = WritableKeys<Props>
144
+ * ```
145
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
146
+ * @see {@link https://stackoverflow.com/questions/52443276/how-to-exclude-getter-only-properties-from-type-in-typescript}
147
+ */
148
+ export type WritableKeys<Target extends AnyHybridRecord> = {
149
+ [Key in keyof Target]-?: IfEquals<{ [Q in Key]: Target[Key] }, { -readonly [Q in Key]: Target[Key] }, Key, never>
150
+ }[keyof Target]
151
+
152
+ /**
153
+ * @example
154
+ * ```
155
+ * type Props = { req: number; reqUndef: number | undefined; opt?: string; optUndef?: number | undefined; };
156
+ * // Expect: "req" | "reqUndef"
157
+ * type Example1 = RequiredKeys<Props>
158
+ * ```
159
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
160
+ * @see {@link https://stackoverflow.com/questions/52984808/is-there-a-way-to-get-all-required-properties-of-a-typescript-object}
161
+ */
162
+ export type RequiredKeys<Target> = {
163
+ [Key in keyof Target]-?: Record<string | number | symbol, never> extends Pick<Target, Key> ? never : Key;
164
+ }[keyof Target]
165
+ /**
166
+ * @example
167
+ * ```
168
+ * type Props = { req: number; reqUndef: number | undefined; opt?: string; optUndef?: number | undefined; };
169
+ * // Expect: "opt" | "optUndef"
170
+ * type Example1 = OptionalKeys<Props>
171
+ * ```
172
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
173
+ * @see {@link https://stackoverflow.com/questions/52984808/is-there-a-way-to-get-all-required-properties-of-a-typescript-object}
174
+ */
175
+ export type OptionalKeys<Target> = {
176
+ [Key in keyof Target]-?: Record<string | number | symbol, never> extends Pick<Target, Key> ? Key : never;
177
+ }[keyof Target]
178
+
179
+ /**
180
+ * @example
181
+ * ```
182
+ * interface Temp { req: number, reqUndef: number | undefined, opt?: string }
183
+ * // Expect: 'req'
184
+ * type Example1 = PickKeysByValue<Temp, number>
185
+ * // Expect: 'req' | 'reqUndef'
186
+ * type Example2 = PickKeysByValue<Temp, number | undefined>
187
+ * ```
188
+ * (For ALL `ByValue` utilities) When we want to get 'opt' as result in above example, `PickKeysByValue<Temp, string>`
189
+ * will not work. We should use `PickKeysByValue<Temp, string | undefined>` instead. It's so weird that we don't always
190
+ * know whether the target key is optional or not in actual most of situations so we have to include `undefined`
191
+ * in the target matching `ValueType`'s union. It's unnecessary and redundant.
192
+ *
193
+ * On the other hand, normal keys and optional keys are quite different. We indeed need an approach to
194
+ * distinguish them. Seems like add `undefined` to the union of optional keys' value type is a reasonable way.
195
+ *
196
+ * Here our final choice is give `undefined` a chance until we get a more fantastic solution. Meanwhile, turn the
197
+ * `exactOptionalPropertyTypes: true` typescript's compiler option on. It will make the use of `undefined` on optional
198
+ * properties more reasonable. For more information on it: see {@link https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes},
199
+ * there's also a use guide on that information, see {@link https://tkdodo.eu/blog/optional-vs-undefined}.
200
+ */
201
+ export type PickKeysByValue<Target, ValueType> = {
202
+ [Key in keyof Target]-?: Target[Key] extends ValueType ? Key : never
203
+ }[keyof Target]
204
+ /**
205
+ * @example
206
+ * ```
207
+ * interface Temp { req: number, reqUndef: number | undefined, opt?: string }
208
+ * // Expect: 'req'
209
+ * type Example1 = PickKeysByValue<Temp, number>
210
+ * // Expect: 'reqUndef'
211
+ * type Example2 = PickKeysByValue<Temp, number | undefined>
212
+ * ```
213
+ */
214
+ export type PickKeysByValueExact<Target, ValueType> = {
215
+ [Key in keyof Target]-?: [ValueType] extends [Target[Key]] ? ([Target[Key]] extends [ValueType] ? Key : never) : never;
216
+ }[keyof Target]
217
+
218
+ /**
219
+ * @example
220
+ * ```
221
+ * interface Temp { req: number, reqUndef: number | undefined, opt?: string }
222
+ * // Expect: { req: number }
223
+ * type Example1 = PickByValue<Temp, number>
224
+ * // Expect: { req: number; reqUndef: number | undefined; }
225
+ * type Example2 = PickByValue<Temp, number | undefined>
226
+ * ```
227
+ * @see {@link https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c}
228
+ */
229
+ export type PickByValue<Target, ValueType> = Pick<Target, PickKeysByValue<Target, ValueType>>
230
+ /**
231
+ * @example
232
+ * ```
233
+ * interface Temp { req: number, reqUndef: number | undefined, opt?: string }
234
+ * // Expect: { req: number }
235
+ * type Example1 = PickByValueExact<Temp, number>
236
+ * // Expect: { reqUndef: number | undefined; }
237
+ * type Example2 = PickByValueExact<Temp, number | undefined>
238
+ * ```
239
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
240
+ */
241
+ export type PickByValueExact<Target, ValueType> = Pick<Target, PickKeysByValueExact<Target, ValueType>>
242
+
243
+ /**
244
+ * @example
245
+ * ```
246
+ * interface Temp { req: number, reqUndef: number | undefined, opt?: string }
247
+ * // Expect: { reqUndef: number | undefined; opt?: string; }
248
+ * type Example1 = OmitByValue<Temp, number>
249
+ * // Expect: { opt?: string; }
250
+ * type Example2 = OmitByValue<Temp, number | undefined>
251
+ * ```
252
+ * @see {@link https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c}
253
+ */
254
+ export type OmitByValue<Target, ValueType> = Omit<Target, PickKeysByValue<Target, ValueType>>
255
+ /**
256
+ * @example
257
+ * ```
258
+ * interface Temp { req: number, reqUndef: number | undefined, opt?: string }
259
+ * // Expect: { reqUndef: number | undefined; opt?: string; }
260
+ * type Example1 = OmitByValueExact<Temp, number>
261
+ * // Expect: { req: number; opt?: string }
262
+ * type Example2 = OmitByValueExact<Temp, number | undefined>
263
+ * ```
264
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
265
+ */
266
+ export type OmitByValueExact<Target, ValueType> = Omit<Target, PickKeysByValueExact<Target, ValueType>>
267
+
268
+ /**
269
+ * ObjectNamedKeys
270
+ * @example
271
+ * ```
272
+ * interface Temp {
273
+ * name: string
274
+ * age?: number
275
+ * [key: string]: string | number
276
+ * }
277
+ * // Expect: 'name' | 'age'
278
+ * type Example1 = ObjectNamedKeys<Temp>
279
+ * ```
280
+ * @see {@link https://github.com/millsp/ts-toolbelt/blob/319e55123b9571d49f34eca3e5926e41ca73e0f3/sources/Any/KnownKeys.ts#L11}
281
+ * @see {@link https://github.com/millsp/ts-toolbelt/issues/164 issue}
282
+ * @see {@link https://stackoverflow.com/questions/51465182/how-to-remove-index-signature-using-mapped-types/51956054#51956054}
283
+ */
284
+ export type ObjectNamedKeys<Target> = keyof {
285
+ [Key in keyof Target as (
286
+ string extends Key ? never : number extends Key ? never : symbol extends Key ? never : Key
287
+ )]: Target[Key]
288
+ }
289
+ export type ObjectNamedParts<Target> = ObjectPrettify<Pick<Target, ObjectNamedKeys<Target>>>
290
+ export type ObjectIndexedParts<Target> = ObjectPrettify<Omit<Target, ObjectNamedKeys<Target>>>
291
+ export type ObjectHasNamedKeys<Target> = ObjectNamedKeys<Target> extends never ? false : true
292
+ export type ObjectHasIndexedKeys<Target> = keyof ObjectIndexedParts<Target> extends never ? false : true
293
+
294
+ // ============================================================================
295
+ // Manipulation
296
+ // ============================================================================
297
+
298
+ /**
299
+ * @example
300
+ * ```
301
+ * interface Temp { a: string, b: number, c?: boolean }
302
+ * // Expect: { a: string | undefined, b: number, c?: boolean }
303
+ * type Example1 = UndefinedableByKeys<Temp, 'a'>
304
+ * ```
305
+ */
306
+ export type UndefinedableByKeys<Target, Keys> = {
307
+ [Key in keyof Target]: Key extends Keys ? Undefinedable<Target[Key]> : Target[Key]
308
+ }
309
+ export type UndefinedableAllKeys<Target> = UndefinedableByKeys<Target, keyof Target>
310
+
311
+ /**
312
+ * @example
313
+ * ```
314
+ * interface Temp { a: string, b: number, c?: boolean }
315
+ * // Expect: { a: string | null, b: number, c?: boolean }
316
+ * type Example1 = NullableByKeys<Temp, 'a'>
317
+ * ```
318
+ */
319
+ export type NullableByKeys<Target, Keys> = {
320
+ [Key in keyof Target]: Key extends Keys ? Nullable<Target[Key]> : Target[Key]
321
+ }
322
+ export type NullableAllKeys<Target> = NullableByKeys<Target, keyof Target>
323
+
324
+ /**
325
+ * @example
326
+ * ```
327
+ * interface Temp { a: string, b: number, c?: boolean }
328
+ * // Expect: { a: string | null | undefined, b: number, c?: boolean }
329
+ * type Example1 = NilableByKeys<Temp, 'a'>
330
+ * ```
331
+ */
332
+ export type NilableByKeys<Target, Keys> = {
333
+ [Key in keyof Target]: Key extends Keys ? Nilable<Target[Key]> : Target[Key]
334
+ }
335
+ export type NilableAllKeys<Target> = NilableByKeys<Target, keyof Target>
336
+
337
+ /**
338
+ * @example
339
+ * ```
340
+ * interface Temp { a: string | undefined, b: number, c?: boolean | undefined }
341
+ * // Expect: { a: string, b: number, c?: boolean }
342
+ * type Example1 = NonUndefinedableAllKeys<Temp>
343
+ * ```
344
+ */
345
+ export type NonUndefinedableAllKeys<Target> = {
346
+ [Key in keyof Target]: NonUndefinedable<Target[Key]>
347
+ }
348
+ /**
349
+ * @example
350
+ * ```
351
+ * interface Temp { a: string | undefined, b: number, c?: boolean }
352
+ * // Expect: { a: string, b: number, c?: boolean }
353
+ * type Example1 = NonUndefinedableByKeys<Temp, 'a'>
354
+ * type Example2 = NonUndefinedableByKeys<Temp, 'a' | 'b'>
355
+ *
356
+ * interface Temp { a: string | undefined, b: number, c?: boolean | undefined }
357
+ * // Expect: { a: string, b: number, c?: boolean }
358
+ * type Example3 = NonUndefinedableByKeys<Temp, 'a' | 'c'>
359
+ * // Expect: { a: string | undefined, b: number, c?: boolean }
360
+ * type Example4 = NonUndefinedableByKeys<Temp, 'c'>
361
+ * ```
362
+ */
363
+ export type NonUndefinedableByKeys<Target, Keys> = ObjectPrettify<
364
+ NonUndefinedableAllKeys<Pick<Target, UnionIntersection<RequiredKeys<Target>, Keys>>>
365
+ & Pick<Target, UnionDifference<RequiredKeys<Target>, Keys>>
366
+ & Partial<NonUndefinedableAllKeys<Pick<Target, UnionIntersection<OptionalKeys<Target>, Keys>>>>
367
+ & Pick<Target, UnionDifference<OptionalKeys<Target>, Keys>>
368
+ >
369
+
370
+ /**
371
+ * @example
372
+ * ```
373
+ * interface Temp { a: string | null, b: number, c?: boolean | null }
374
+ * // Expect: { a: string, b: number, c?: boolean }
375
+ * type Example1 = NonNullableAllKeys<Temp>
376
+ * ```
377
+ */
378
+ export type NonNullableAllKeys<Target> = {
379
+ [Key in keyof Target]: NonNullable<Target[Key]>
380
+ }
381
+ /**
382
+ * @example
383
+ * ```
384
+ * interface Temp { a: string | null, b: number, c?: boolean }
385
+ * // Expect: { a: string, b: number, c?: boolean }
386
+ * type Example1 = NonNullableByKeys<Temp, 'a'>
387
+ * type Example2 = NonNullableByKeys<Temp, 'a' | 'b'>
388
+ *
389
+ * interface Temp { a: string | null, b: number, c?: boolean | null }
390
+ * // Expect: { a: string, b: number, c?: boolean }
391
+ * type Example3 = NonNullableByKeys<Temp, 'a' | 'c'>
392
+ * // Expect: { a: string | null, b: number, c?: boolean }
393
+ * type Example4 = NonNullableByKeys<Temp, 'c'>
394
+ * ```
395
+ */
396
+ export type NonNullableByKeys<Target, Keys> = ObjectPrettify<
397
+ NonNullableAllKeys<Pick<Target, UnionIntersection<RequiredKeys<Target>, Keys>>>
398
+ & Pick<Target, UnionDifference<RequiredKeys<Target>, Keys>>
399
+ & Partial<NonNullableAllKeys<Pick<Target, UnionIntersection<OptionalKeys<Target>, Keys>>>>
400
+ & Pick<Target, UnionDifference<OptionalKeys<Target>, Keys>>
401
+ >
402
+
403
+ /**
404
+ * @example
405
+ * ```
406
+ * interface Temp { a: string | null | undefined, b: number, c?: boolean | null }
407
+ * // Expect: { a: string, b: number, c?: boolean }
408
+ * type Example1 = NonNilableAllKeys<Temp>
409
+ * ```
410
+ */
411
+ export type NonNilableAllKeys<Target> = {
412
+ [Key in keyof Target]: NonNilable<Target[Key]>
413
+ }
414
+ /**
415
+ * @example
416
+ * ```
417
+ * interface Temp { a: string | null | undefined, b: number, c?: boolean }
418
+ * // Expect: { a: string, b: number, c?: boolean }
419
+ * type Example1 = NonNilableByKeys<Temp, 'a'>
420
+ * type Example2 = NonNilableByKeys<Temp, 'a' | 'b'>
421
+ *
422
+ * interface Temp { a: string | null | undefined, b: number, c?: boolean | null | undefined }
423
+ * // Expect: { a: string, b: number, c?: boolean }
424
+ * type Example3 = NonNilableByKeys<Temp, 'a' | 'c'>
425
+ * // Expect: { a: string | null | undefined, b: number, c?: boolean }
426
+ * type Example4 = NonNilableByKeys<Temp, 'c'>
427
+ * ```
428
+ */
429
+ export type NonNilableByKeys<Target, Keys> = ObjectPrettify<
430
+ NonNilableAllKeys<Pick<Target, UnionIntersection<RequiredKeys<Target>, Keys>>>
431
+ & Pick<Target, UnionDifference<RequiredKeys<Target>, Keys>>
432
+ & Partial<NonNilableAllKeys<Pick<Target, UnionIntersection<OptionalKeys<Target>, Keys>>>>
433
+ & Pick<Target, UnionDifference<OptionalKeys<Target>, Keys>>
434
+ >
435
+
436
+ /**
437
+ * @example
438
+ * ```
439
+ * interface Temp { a?: string | undefined, b?: number, c?: boolean }
440
+ * // Expect: { readonly a: string | undefined, readonly b: number, readonly c: boolean }
441
+ * type Example1 = ReadonlyAllKeys<Temp>
442
+ * ```
443
+ */
444
+ export type ReadonlyAllKeys<Target> = {
445
+ +readonly [Key in keyof Target]: Target[Key]
446
+ }
447
+ /**
448
+ * @example
449
+ * ```
450
+ * interface Temp { a?: string | undefined, b?: number, c?: boolean }
451
+ * // Expect: { readonly a: string | undefined, readonly b: number, readonly c: boolean }
452
+ * type Example1 = ReadonlyByKeys<Temp, 'a' | 'b' | 'c'>
453
+ * ```
454
+ */
455
+ export type ReadonlyByKeys<Target, Keys> = ObjectPrettify<
456
+ ReadonlyAllKeys<Pick<Target, UnionIntersection<keyof Target, Keys>>> & Pick<Target, UnionDifference<keyof Target, Keys>>
457
+ >
458
+
459
+ /**
460
+ * @example
461
+ * ```
462
+ * interface Temp { readonly a?: string | undefined, readonly b?: number, readonly c?: boolean }
463
+ * // Expect: { a: string | undefined, b: number, c: boolean }
464
+ * type Example1 = WritableAllKeys<Temp>
465
+ * ```
466
+ */
467
+ export type WritableAllKeys<Target> = {
468
+ -readonly [Key in keyof Target]: Target[Key]
469
+ }
470
+ /**
471
+ * @example
472
+ * ```
473
+ * interface Temp { readonly a?: string | undefined, readonly b?: number, readonly c?: boolean }
474
+ * // Expect: { a: string | undefined, b: number, c: boolean }
475
+ * type Example1 = WritableByKeys<Temp, 'a' | 'b' | 'c'>
476
+ * ```
477
+ */
478
+ export type WritableByKeys<Target, Keys> = ObjectPrettify<
479
+ WritableAllKeys<Pick<Target, UnionIntersection<keyof Target, Keys>>> & Pick<Target, UnionDifference<keyof Target, Keys>>
480
+ >
481
+
482
+ /**
483
+ * @example
484
+ * ```
485
+ * interface Temp { a?: string | undefined, b?: number, c?: boolean }
486
+ * // Expect: { a: string | undefined, b: number, c: boolean }
487
+ * type Example1 = RequiredAllKeys<Temp>
488
+ * ```
489
+ */
490
+ export type RequiredAllKeys<Target> = {
491
+ [Key in keyof Target]-?: Target[Key]
492
+ }
493
+ /**
494
+ * @example
495
+ * ```
496
+ * interface Temp { a?: string | undefined, b?: number, c?: boolean }
497
+ * // Expect: { a: string | undefined, b: number, c: boolean }
498
+ * type Example1 = RequiredByKeys<Temp, 'a' | 'b' | 'c'>
499
+ * ```
500
+ */
501
+ export type RequiredByKeys<Target, Keys> = ObjectPrettify<
502
+ RequiredAllKeys<Pick<Target, UnionIntersection<keyof Target, Keys>>> & Pick<Target, UnionDifference<keyof Target, Keys>>
503
+ >
504
+
505
+ /**
506
+ * @example
507
+ * ```
508
+ * interface Temp { a: string | undefined, b: number, c?: boolean | undefined }
509
+ * // Expect: { a?: string | undefined, b?: number, c?: boolean | undefined }
510
+ * type Example1 = OptionalAllKeys<Temp>
511
+ * ```
512
+ */
513
+ export type OptionalAllKeys<Target> = {
514
+ [Key in keyof Target]+?: Target[Key]
515
+ }
516
+ /**
517
+ * @example
518
+ * ```
519
+ * interface Temp { a: string | undefined, b: number, c?: boolean | undefined }
520
+ * // Expect: { a?: string | undefined, b?: number, c?: boolean }
521
+ * type Example1 = OptionalByKeys<Temp, 'a' | 'b' | 'c'>
522
+ * ```
523
+ */
524
+ export type OptionalByKeys<Target, Keys> = ObjectPrettify<
525
+ OptionalAllKeys<Pick<Target, UnionIntersection<keyof Target, Keys>>> & Pick<Target, UnionDifference<keyof Target, Keys>>
526
+ >
527
+
528
+ /**
529
+ * Given a type `{ a?: string, b: number }`, return `{ a: string, b?: number }`.
530
+ *
531
+ * @example
532
+ * ```
533
+ * interface Temp { a: string, b?: number, c?: boolean }
534
+ * // Expect: { a?: string, b: number, c: boolean }
535
+ * type Example1 = ReverseOptional<Temp>
536
+ * ```
537
+ * @see {@link ReverseRequired}
538
+ * @see {@link https://stackoverflow.com/questions/57593022/reverse-required-and-optional-properties}
539
+ */
540
+ export type ReverseOptional<Target> = ObjectPrettify<
541
+ Required<Pick<Target, OptionalKeys<Target>>> & OptionalAllKeys<Omit<Target, OptionalKeys<Target>>>
542
+ >
543
+ /**
544
+ * @see {@link ReverseOptional}
545
+ */
546
+ export type ReverseRequired<Target> = ReverseOptional<Target>
547
+
548
+ /**
549
+ * @example
550
+ * ```
551
+ * interface Temp { a: string, b?: number, c?: boolean }
552
+ *
553
+ * // Expect: { a: string, b: number, c?: boolean }
554
+ * type Example1 = ReverseOptionalByKeys<Temp, 'b'>
555
+ * ```
556
+ */
557
+ export type ReverseOptionalByKeys<Target, Keys extends keyof Target> = ObjectPrettify<
558
+ Omit<Target, Keys> & ReverseOptional<Pick<Target, Keys>>
559
+ >
560
+ /**
561
+ * @see {@link ReverseOptionalByKeys}
562
+ */
563
+ export type ReverseRequiredByKeys<Target, Keys extends keyof Target> = ReverseOptionalByKeys<Target, Keys>
564
+
565
+ /**
566
+ * @example
567
+ * ```
568
+ * type Props = { name: string; age: number; visible: boolean };
569
+ * type DefaultProps = { age: number };
570
+ * // Expect: { age: number; }
571
+ * type Example1 = ObjectIntersection<Props, DefaultProps>
572
+ * ```
573
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
574
+ */
575
+ export type ObjectIntersection<T extends AnyHybridRecord, U extends AnyHybridRecord> = Pick<T, UnionIntersection<keyof T, keyof U>>
576
+
577
+ /**
578
+ * @example
579
+ * ```
580
+ * type Props = { name: string; age: number; visible: boolean };
581
+ * type DefaultProps = { age: number };
582
+ * // Expect: { name: string; visible: boolean; }
583
+ * type Example1 = ObjectDifference<Props, DefaultProps>
584
+ * ```
585
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
586
+ */
587
+ export type ObjectDifference<T extends AnyHybridRecord, U extends AnyHybridRecord> = Pick<T, UnionDifference<keyof T, keyof U>>
588
+
589
+ /**
590
+ * @example
591
+ * ```
592
+ * type Props = { name: string; age: number; visible: boolean };
593
+ * type DefaultProps = { age: number };
594
+ * // Expect: { name: string; visible: boolean; }
595
+ * type Example1 = ObjectComplement<Props, DefaultProps>
596
+ * ```
597
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
598
+ */
599
+ export type ObjectComplement<T extends SuperT, SuperT extends AnyHybridRecord> = Pick<T, UnionComplement<keyof T, keyof SuperT>>
600
+
601
+ /**
602
+ * @example
603
+ * ```
604
+ * interface PropsA { name: string, age: number, visible: boolean }
605
+ * interface PropsB { age: number, sex: string }
606
+ * // Expect: { name: string; visible: boolean; sex: string };
607
+ * type Example1 = ObjectSymmetricDifference<PropsA, PropsB>
608
+ * // Expect: 'name' | 'visible' | 'sex'
609
+ * type Example2 = keyof ObjectSymmetricDifference<PropsA, PropsB>
610
+ * ```
611
+ */
612
+ export type ObjectSymmetricDifference<T extends AnyHybridRecord, U extends AnyHybridRecord> = ObjectPrettify<
613
+ ObjectDifference<T, U> & ObjectDifference<U, T>
614
+ >
615
+
616
+ /**
617
+ * @example
618
+ * ```
619
+ * interface Props { name: string, age: number, visible: boolean }
620
+ * interface NewProps { age: string, other: string }
621
+ * // Expect: { name: string; age: string; visible: boolean; }
622
+ * type Example1 = ObjectOverwrite<Props, NewProps>
623
+ * ```
624
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
625
+ */
626
+ export type ObjectOverwrite<Target extends AnyHybridRecord, Patch extends AnyHybridRecord> = ObjectPrettify<
627
+ ObjectDifference<Target, Patch> & ObjectIntersection<Patch, Target>
628
+ >
629
+
630
+ /**
631
+ * @example
632
+ * ```
633
+ * interface Props { name: string, age: number, visible: boolean }
634
+ * interface NewProps { age: string, other: string }
635
+ * // Expect: { name: string; age: string; visible: boolean; other: string; }
636
+ * type Example1 = ObjectAssign<Props, NewProps>
637
+ * ```
638
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
639
+ */
640
+ export type ObjectAssign<Target extends AnyHybridRecord, Patch extends AnyHybridRecord> = ObjectPrettify<
641
+ // ObjectDifference<Target, Patch> & ObjectIntersection<Patch, Target> & ObjectDifference<Patch, Target>
642
+ Omit<Target, keyof Patch> & Patch
643
+ >
644
+ /**
645
+ * Alias for `ObjectAssign`, defined for semantic of `ObjectMergeN`.
646
+ * @see {@link ObjectAssign}
647
+ */
648
+ export type ObjectMerge<Target extends AnyHybridRecord, Patch extends AnyHybridRecord> = ObjectAssign<Target, Patch>
649
+
650
+ type InternalObjectMergeN<Targets extends AnyHybridRecord[], Result extends AnyHybridRecord> = Targets extends [infer Head, ...infer Tail] ?
651
+ InternalObjectMergeN<Tail extends AnyHybridRecord[] ? Tail : [], ObjectMerge<Result, Head extends AnyHybridRecord ? Head : {}>> : Result
652
+ /**
653
+ * @example
654
+ * ```
655
+ * interface a { a: string }
656
+ * interface b { readonly b: string }
657
+ * interface c { c?: string }
658
+ * // Expect: { a: string; readonly b: string; c?: string; }
659
+ * type Example1 = ObjectMergeN<[a, b, c]>
660
+ * ```
661
+ */
662
+ export type ObjectMergeN<Targets extends AnyHybridRecord[]> = ObjectPrettify<InternalObjectMergeN<Targets, {}>>
663
+
664
+ /**
665
+ * @example
666
+ * ```
667
+ * interface Props { name: string, age: number, visible: boolean }
668
+ * // Expect: { name: string; } | { age: number; } | { visible: boolean; }
669
+ * type UnionizedType = ObjectUnionize<Props>
670
+ * ```
671
+ * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts}
672
+ */
673
+ export type ObjectUnionize<Target extends AnyHybridRecord> = {
674
+ [Key in keyof Target]: { [Q in Key]: Target[Key] };
675
+ }[keyof Target]
676
+
677
+ /**
678
+ * @example
679
+ * ```
680
+ * interface Temp {
681
+ * readonly grandpa: {
682
+ * readonly name: string
683
+ * father?: {
684
+ * readonly name?: string
685
+ * son: {
686
+ * readonly name?: string
687
+ * }
688
+ * }
689
+ * }
690
+ * }
691
+ * // Expect: { grandpa?: { name?: string, father?: { name?: string, son?: { name?: string } } } }
692
+ * type Example1 = ObjectDeepWritable<Temp>
693
+ * ```
694
+ */
695
+ export type ObjectDeepWritable<Target extends AnyStringRecord> = {
696
+ -readonly [Key in keyof Target]: Target[Key] extends (AnyStringRecord | undefined) ?
697
+ ObjectDeepWritable<NonUndefinedable<Target[Key]>> : Target[Key];
698
+ }
699
+
700
+ /**
701
+ * @example
702
+ * ```
703
+ * interface Temp {
704
+ * grandpa: {
705
+ * name: string
706
+ * father?: {
707
+ * name?: string
708
+ * son: {
709
+ * name?: string
710
+ * }
711
+ * }
712
+ * }
713
+ * }
714
+ * // Expect: { readonly grandpa?: {
715
+ * // readonly name?: string, readonly father?: { readonly name?: string, readonly son?: { readonly name?: string } }
716
+ * // } }
717
+ * type Example1 = ObjectDeepReadonly<Temp>
718
+ * ```
719
+ */
720
+ export type ObjectDeepReadonly<Target extends AnyStringRecord> = {
721
+ +readonly [Key in keyof Target]: Target[Key] extends (AnyStringRecord | undefined) ?
722
+ ObjectDeepReadonly<NonUndefinedable<Target[Key]>> : Target[Key];
723
+ }
724
+
725
+ /**
726
+ * @example
727
+ * ```
728
+ * interface Temp {
729
+ * grandpa: {
730
+ * name: string
731
+ * father?: {
732
+ * name?: string
733
+ * son: {
734
+ * name?: string
735
+ * }
736
+ * }
737
+ * }
738
+ * }
739
+ * // Expect: { grandpa: { name: string, father: { name: string, son: { name: string } } } }
740
+ * type Example1 = ObjectDeepRequired<Temp>
741
+ * ```
742
+ */
743
+ export type ObjectDeepRequired<Target extends AnyStringRecord> = {
744
+ [Key in keyof Target]-?: Target[Key] extends (AnyStringRecord | undefined) ?
745
+ ObjectDeepRequired<NonUndefinedable<Target[Key]>> : Target[Key];
746
+ }
747
+
748
+ /**
749
+ * @example
750
+ * ```
751
+ * interface Temp {
752
+ * grandpa: {
753
+ * name: string
754
+ * father?: {
755
+ * name?: string
756
+ * son: {
757
+ * name?: string
758
+ * }
759
+ * }
760
+ * }
761
+ * }
762
+ * // Expect: { grandpa?: { name?: string, father?: { name?: string, son?: { name?: string } } } }
763
+ * type Example1 = ObjectDeepOptional<Temp>
764
+ * ```
765
+ */
766
+ export type ObjectDeepOptional<Target extends AnyStringRecord> = {
767
+ [Key in keyof Target]+?: Target[Key] extends (AnyStringRecord | undefined) ?
768
+ ObjectDeepOptional<NonUndefinedable<Target[Key]>> : Target[Key];
769
+ }
770
+
771
+ // ============================================================================
772
+ // Conversion
773
+ // ============================================================================
774
+
775
+ /**
776
+ * Extract method signature as a standalone function.
777
+ *
778
+ * @example
779
+ * ```
780
+ * type Obj = { method(a: number, b: string): boolean }
781
+ * // Expect: (a: number, b: string) => boolean
782
+ * type Example1 = ObjectToFunction<Obj, 'method'>
783
+ * ```
784
+ */
785
+ export type ObjectToFunction<T, Key extends keyof T> =
786
+ T[Key] extends (...args: infer P) => infer R
787
+ ? (...args: P) => R
788
+ : never