uni-types 1.0.0 → 1.1.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.
- package/README.md +146 -176
- package/dist/index.d.cts +825 -52
- package/dist/index.d.mts +825 -52
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,97 @@
|
|
|
1
|
+
//#region src/brand/index.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Brand/Opaque types for nominal typing
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Brand a type for nominal typing
|
|
7
|
+
* Creates a unique type that cannot be accidentally mixed with other branded types
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* type UserId = Brand<string, 'UserId'>
|
|
12
|
+
* type OrderId = Brand<string, 'OrderId'>
|
|
13
|
+
*
|
|
14
|
+
* const userId: UserId = 'user-123' as UserId
|
|
15
|
+
* const orderId: OrderId = 'order-456' as OrderId
|
|
16
|
+
*
|
|
17
|
+
* // These won't mix - type safety!
|
|
18
|
+
* // const wrong: OrderId = userId // Error!
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
type Brand<T, B extends string> = T & {
|
|
22
|
+
__brand: B;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Unbrand a branded type - extracts the underlying type
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* type UserId = Brand<string, 'UserId'>
|
|
30
|
+
* Unbrand<UserId> // string
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
type Unbrand<T> = T extends Brand<infer U, infer _> ? U : T;
|
|
34
|
+
/**
|
|
35
|
+
* Common branded types for convenience
|
|
36
|
+
*/
|
|
37
|
+
type BrandedString<B extends string> = Brand<string, B>;
|
|
38
|
+
type BrandedNumber<B extends string> = Brand<number, B>;
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/conditional/index.d.ts
|
|
41
|
+
/**
|
|
42
|
+
* Conditional type utilities for cleaner type logic
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* If-then-else at type level
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* If<true, string, number> // string
|
|
50
|
+
* If<false, string, number> // number
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
type If<C extends boolean, T, F> = C extends true ? T : F;
|
|
54
|
+
/**
|
|
55
|
+
* Not operator for boolean types
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* Not<true> // false
|
|
60
|
+
* Not<false> // true
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
type Not<B extends boolean> = B extends true ? false : true;
|
|
64
|
+
/**
|
|
65
|
+
* And operator for boolean types
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* And<true, true> // true
|
|
70
|
+
* And<true, false> // false
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
type And<A extends boolean, B extends boolean> = A extends true ? B : false;
|
|
74
|
+
/**
|
|
75
|
+
* Or operator for boolean types
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* Or<true, false> // true
|
|
80
|
+
* Or<false, false> // false
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
type Or<A extends boolean, B extends boolean> = A extends true ? true : B;
|
|
84
|
+
/**
|
|
85
|
+
* Type constraint assertion - ensures T extends U
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* Assert<string | number, string> // string
|
|
90
|
+
* Assert<string, number> // never
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
type Assert<T, U extends T> = T extends U ? T : never;
|
|
94
|
+
//#endregion
|
|
1
95
|
//#region src/core/omit.d.ts
|
|
2
96
|
/**
|
|
3
97
|
* Make all properties required except specified ones
|
|
@@ -111,7 +205,7 @@ type Last<T extends readonly unknown[]> = T extends readonly [...unknown[], infe
|
|
|
111
205
|
* Tail<[1]> // []
|
|
112
206
|
* ```
|
|
113
207
|
*/
|
|
114
|
-
type Tail<T extends readonly unknown[]> = T extends readonly [unknown, ...infer R] ? R : [];
|
|
208
|
+
type Tail$1<T extends readonly unknown[]> = T extends readonly [unknown, ...infer R] ? R : [];
|
|
115
209
|
/**
|
|
116
210
|
* Get all elements except the last (init)
|
|
117
211
|
*
|
|
@@ -160,6 +254,109 @@ type TupleLength<T extends readonly unknown[]> = T['length'];
|
|
|
160
254
|
*/
|
|
161
255
|
type IsEmptyTuple<T extends readonly unknown[]> = T extends readonly [] ? true : false;
|
|
162
256
|
//#endregion
|
|
257
|
+
//#region src/utils/path.d.ts
|
|
258
|
+
type Primitive$1 = string | number | boolean | null | undefined | symbol | bigint;
|
|
259
|
+
type Join<K, P> = K extends string | number ? P extends string | number ? `${K}${'' extends P ? '' : '.'}${P}` : never : never;
|
|
260
|
+
type Prev$1 = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
|
|
261
|
+
/**
|
|
262
|
+
* Get all possible paths to nested properties
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* ```ts
|
|
266
|
+
* interface Obj {
|
|
267
|
+
* a: {
|
|
268
|
+
* b: string
|
|
269
|
+
* c: {
|
|
270
|
+
* d: number
|
|
271
|
+
* }
|
|
272
|
+
* }
|
|
273
|
+
* }
|
|
274
|
+
*
|
|
275
|
+
* type P = Paths<Obj>
|
|
276
|
+
* // 'a' | 'a.b' | 'a.c' | 'a.c.d'
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
279
|
+
type Paths<T, D extends number = 10> = [D] extends [never] ? never : T extends Primitive$1 ? never : { [K in keyof T]: T[K] extends Primitive$1 ? `${K & string}` : Join<K, Paths<T[K], Prev$1[D]>> }[keyof T];
|
|
280
|
+
/**
|
|
281
|
+
* Get the value type at a given path
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```ts
|
|
285
|
+
* interface Obj {
|
|
286
|
+
* a: {
|
|
287
|
+
* b: string
|
|
288
|
+
* }
|
|
289
|
+
* }
|
|
290
|
+
*
|
|
291
|
+
* type V = PathValue<Obj, 'a.b'> // string
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
type PathValue<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? PathValue<T[K], Rest> : never : P extends keyof T ? T[P] : never;
|
|
295
|
+
/**
|
|
296
|
+
* Split a path string into an array
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```ts
|
|
300
|
+
* SplitPath<'a.b.c'> // ['a', 'b', 'c']
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
type SplitPath<S extends string, Acc extends string[] = []> = S extends `${infer H}.${infer T}` ? SplitPath<T, [...Acc, H]> : S extends `${infer H}` ? [...Acc, H] : Acc;
|
|
304
|
+
//#endregion
|
|
305
|
+
//#region src/deep/path.d.ts
|
|
306
|
+
type PathSegments<_T, P extends string> = P extends '' ? [] : SplitPath<P>;
|
|
307
|
+
/**
|
|
308
|
+
* Deep omit by path - removes properties at specified paths
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* ```ts
|
|
312
|
+
* interface User {
|
|
313
|
+
* profile: {
|
|
314
|
+
* name: string
|
|
315
|
+
* email: string
|
|
316
|
+
* settings: {
|
|
317
|
+
* theme: string
|
|
318
|
+
* lang: string
|
|
319
|
+
* }
|
|
320
|
+
* }
|
|
321
|
+
* }
|
|
322
|
+
*
|
|
323
|
+
* DeepOmit<User, 'profile.settings'>
|
|
324
|
+
* // { profile: { name: string; email: string } }
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
type DeepOmit<T, P extends string> = T extends object ? P extends '' ? T : DeepOmitBySegments<T, PathSegments<T, P>> : T;
|
|
328
|
+
type DeepOmitBySegments<T, Segments extends string[]> = Segments extends [infer First extends string, ...infer Rest extends string[]] ? First extends keyof T ? Rest extends [] ? Omit<T, First> : { [K in keyof T]: K extends First ? DeepOmitBySegments<T[K], Rest> : T[K] } : T : T;
|
|
329
|
+
/**
|
|
330
|
+
* Deep pick by path - keeps only properties at specified paths
|
|
331
|
+
*
|
|
332
|
+
* @example
|
|
333
|
+
* ```ts
|
|
334
|
+
* interface User {
|
|
335
|
+
* profile: {
|
|
336
|
+
* name: string
|
|
337
|
+
* email: string
|
|
338
|
+
* settings: {
|
|
339
|
+
* theme: string
|
|
340
|
+
* lang: string
|
|
341
|
+
* }
|
|
342
|
+
* }
|
|
343
|
+
* }
|
|
344
|
+
*
|
|
345
|
+
* DeepPick<User, 'profile.name' | 'profile.settings.theme'>
|
|
346
|
+
* // { profile: { name: string; settings: { theme: string } } }
|
|
347
|
+
* ```
|
|
348
|
+
*/
|
|
349
|
+
type DeepPick<T, P extends string> = T extends object ? P extends '' ? T : DeepPickBySegments<T, PathSegments<T, P>> : T;
|
|
350
|
+
type DeepPickBySegments<T, Segments extends string[]> = Segments extends [infer First extends string, ...infer Rest extends string[]] ? First extends keyof T ? Rest extends [] ? Pick<T, First> : { [K in First]: DeepPickBySegments<T[K], Rest> } : Record<string, never> : T;
|
|
351
|
+
/**
|
|
352
|
+
* Deep pick for union paths
|
|
353
|
+
*/
|
|
354
|
+
type DeepPickPaths<T, P extends string> = P extends P ? DeepPick<T, P> : never;
|
|
355
|
+
/**
|
|
356
|
+
* Deep omit for union paths
|
|
357
|
+
*/
|
|
358
|
+
type DeepOmitPaths<T, P extends string> = P extends P ? DeepOmit<T, P> : never;
|
|
359
|
+
//#endregion
|
|
163
360
|
//#region src/deep/index.d.ts
|
|
164
361
|
type BuiltIn = Date | ((...args: unknown[]) => unknown) | Map<unknown, unknown> | Set<unknown> | RegExp;
|
|
165
362
|
/**
|
|
@@ -231,6 +428,123 @@ type DeepReadonly<T> = T extends BuiltIn ? T : T extends Map<infer K, infer V> ?
|
|
|
231
428
|
*/
|
|
232
429
|
type DeepMutable<T> = T extends BuiltIn ? T : T extends Map<infer K, infer V> ? Map<DeepMutable<K>, DeepMutable<V>> : T extends Set<infer V> ? Set<DeepMutable<V>> : T extends readonly (infer E)[] ? DeepMutable<E>[] : T extends object ? { -readonly [P in keyof T]: DeepMutable<T[P]> } : T;
|
|
233
430
|
//#endregion
|
|
431
|
+
//#region src/functions/index.d.ts
|
|
432
|
+
/**
|
|
433
|
+
* Function type utilities
|
|
434
|
+
*/
|
|
435
|
+
/**
|
|
436
|
+
* Get function parameters as tuple
|
|
437
|
+
*
|
|
438
|
+
* @example
|
|
439
|
+
* ```ts
|
|
440
|
+
* type Fn = (a: string, b: number) => boolean
|
|
441
|
+
* Parameters<Fn> // [string, number]
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
444
|
+
type Parameters<T> = T extends ((...args: infer P) => any) ? P : never;
|
|
445
|
+
/**
|
|
446
|
+
* Get function return type
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* ```ts
|
|
450
|
+
* type Fn = (a: string) => number
|
|
451
|
+
* ReturnType<Fn> // number
|
|
452
|
+
* ```
|
|
453
|
+
*/
|
|
454
|
+
type ReturnType<T> = T extends ((...args: any[]) => infer R) ? R : any;
|
|
455
|
+
/**
|
|
456
|
+
* Get Nth parameter type (0-indexed)
|
|
457
|
+
*
|
|
458
|
+
* @example
|
|
459
|
+
* ```ts
|
|
460
|
+
* type Fn = (a: string, b: number, c: boolean) => void
|
|
461
|
+
* NthParameter<Fn, 0> // string
|
|
462
|
+
* NthParameter<Fn, 1> // number
|
|
463
|
+
* NthParameter<Fn, 2> // boolean
|
|
464
|
+
* ```
|
|
465
|
+
*/
|
|
466
|
+
type NthParameter<T, N extends number> = T extends ((...args: infer P) => any) ? P[N] : never;
|
|
467
|
+
/**
|
|
468
|
+
* Extract async function return type (unwraps Promise)
|
|
469
|
+
*
|
|
470
|
+
* @example
|
|
471
|
+
* ```ts
|
|
472
|
+
* type AsyncFn = () => Promise<string>
|
|
473
|
+
* AsyncReturnType<AsyncFn> // string
|
|
474
|
+
* ```
|
|
475
|
+
*/
|
|
476
|
+
type AsyncReturnType<T> = T extends ((...args: any[]) => Promise<infer R>) ? R : T extends ((...args: any[]) => infer R) ? R : never;
|
|
477
|
+
/**
|
|
478
|
+
* Get function this parameter type
|
|
479
|
+
*
|
|
480
|
+
* @example
|
|
481
|
+
* ```ts
|
|
482
|
+
* type Fn = (this: { x: number }) => void
|
|
483
|
+
* ThisParameterType<Fn> // { x: number }
|
|
484
|
+
* ```
|
|
485
|
+
*/
|
|
486
|
+
type ThisParameterType<T> = T extends ((this: infer U, ...args: any[]) => any) ? U : unknown;
|
|
487
|
+
/**
|
|
488
|
+
* Omit this parameter from function type
|
|
489
|
+
*
|
|
490
|
+
* @example
|
|
491
|
+
* ```ts
|
|
492
|
+
* type Fn = (this: { x: number }, a: string) => void
|
|
493
|
+
* OmitThisParameter<Fn> // (a: string) => void
|
|
494
|
+
* ```
|
|
495
|
+
*/
|
|
496
|
+
type OmitThisParameter<T> = T extends ((this: any, ...args: infer A) => infer R) ? (...args: A) => R : T;
|
|
497
|
+
/**
|
|
498
|
+
* Check if type is a function
|
|
499
|
+
*
|
|
500
|
+
* @example
|
|
501
|
+
* ```ts
|
|
502
|
+
* IsFunction<() => void> // true
|
|
503
|
+
* IsFunction<string> // false
|
|
504
|
+
* ```
|
|
505
|
+
*/
|
|
506
|
+
type IsFunction<T> = T extends ((...args: any[]) => any) ? true : false;
|
|
507
|
+
/**
|
|
508
|
+
* Check if type is an async function
|
|
509
|
+
*
|
|
510
|
+
* @example
|
|
511
|
+
* ```ts
|
|
512
|
+
* IsAsyncFunction<() => Promise<string>> // true
|
|
513
|
+
* IsAsyncFunction<() => string> // false
|
|
514
|
+
* ```
|
|
515
|
+
*/
|
|
516
|
+
type IsAsyncFunction<T> = T extends ((...args: any[]) => Promise<any>) ? true : false;
|
|
517
|
+
/**
|
|
518
|
+
* Make function parameters optional
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* ```ts
|
|
522
|
+
* type Fn = (a: string, b: number) => void
|
|
523
|
+
* OptionalParameters<Fn> // (a?: string, b?: number) => void
|
|
524
|
+
* ```
|
|
525
|
+
*/
|
|
526
|
+
type OptionalParameters<T> = T extends ((...args: any[]) => infer R) ? (...args: Partial<Parameters<T>>) => R : never;
|
|
527
|
+
/**
|
|
528
|
+
* Append a parameter to a function
|
|
529
|
+
*
|
|
530
|
+
* @example
|
|
531
|
+
* ```ts
|
|
532
|
+
* type Fn = (a: string) => void
|
|
533
|
+
* AppendParameter<Fn, number> // (a: string, b: number) => void
|
|
534
|
+
* ```
|
|
535
|
+
*/
|
|
536
|
+
type AppendParameter<T, P> = T extends ((...args: infer A) => infer R) ? (...args: [...A, P]) => R : never;
|
|
537
|
+
/**
|
|
538
|
+
* Prepend a parameter to a function
|
|
539
|
+
*
|
|
540
|
+
* @example
|
|
541
|
+
* ```ts
|
|
542
|
+
* type Fn = (a: string) => void
|
|
543
|
+
* PrependParameter<Fn, number> // (a: number, b: string) => void
|
|
544
|
+
* ```
|
|
545
|
+
*/
|
|
546
|
+
type PrependParameter<T, P> = T extends ((...args: infer A) => infer R) ? (...args: [P, ...A]) => R : never;
|
|
547
|
+
//#endregion
|
|
234
548
|
//#region src/guards/index.d.ts
|
|
235
549
|
/**
|
|
236
550
|
* Check if type is an array
|
|
@@ -345,54 +659,6 @@ type FunctionOnly<T> = Pick<T, FunctionKeys<T>>;
|
|
|
345
659
|
*/
|
|
346
660
|
type DataOnly<T> = Pick<T, NonFunctionKeys<T>>;
|
|
347
661
|
//#endregion
|
|
348
|
-
//#region src/utils/path.d.ts
|
|
349
|
-
type Primitive = string | number | boolean | null | undefined | symbol | bigint;
|
|
350
|
-
type Join<K, P> = K extends string | number ? P extends string | number ? `${K}${'' extends P ? '' : '.'}${P}` : never : never;
|
|
351
|
-
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
|
|
352
|
-
/**
|
|
353
|
-
* Get all possible paths to nested properties
|
|
354
|
-
*
|
|
355
|
-
* @example
|
|
356
|
-
* ```ts
|
|
357
|
-
* interface Obj {
|
|
358
|
-
* a: {
|
|
359
|
-
* b: string
|
|
360
|
-
* c: {
|
|
361
|
-
* d: number
|
|
362
|
-
* }
|
|
363
|
-
* }
|
|
364
|
-
* }
|
|
365
|
-
*
|
|
366
|
-
* type P = Paths<Obj>
|
|
367
|
-
* // 'a' | 'a.b' | 'a.c' | 'a.c.d'
|
|
368
|
-
* ```
|
|
369
|
-
*/
|
|
370
|
-
type Paths<T, D extends number = 10> = [D] extends [never] ? never : T extends Primitive ? never : { [K in keyof T]: T[K] extends Primitive ? `${K & string}` : Join<K, Paths<T[K], Prev[D]>> }[keyof T];
|
|
371
|
-
/**
|
|
372
|
-
* Get the value type at a given path
|
|
373
|
-
*
|
|
374
|
-
* @example
|
|
375
|
-
* ```ts
|
|
376
|
-
* interface Obj {
|
|
377
|
-
* a: {
|
|
378
|
-
* b: string
|
|
379
|
-
* }
|
|
380
|
-
* }
|
|
381
|
-
*
|
|
382
|
-
* type V = PathValue<Obj, 'a.b'> // string
|
|
383
|
-
* ```
|
|
384
|
-
*/
|
|
385
|
-
type PathValue<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? PathValue<T[K], Rest> : never : P extends keyof T ? T[P] : never;
|
|
386
|
-
/**
|
|
387
|
-
* Split a path string into an array
|
|
388
|
-
*
|
|
389
|
-
* @example
|
|
390
|
-
* ```ts
|
|
391
|
-
* SplitPath<'a.b.c'> // ['a', 'b', 'c']
|
|
392
|
-
* ```
|
|
393
|
-
*/
|
|
394
|
-
type SplitPath<S extends string, Acc extends string[] = []> = S extends `${infer H}.${infer T}` ? SplitPath<T, [...Acc, H]> : S extends `${infer H}` ? [...Acc, H] : Acc;
|
|
395
|
-
//#endregion
|
|
396
662
|
//#region src/utils/index.d.ts
|
|
397
663
|
/**
|
|
398
664
|
* Merge two types (latter overrides former)
|
|
@@ -412,7 +678,7 @@ type Merge<T, U> = Omit<T, keyof U> & U;
|
|
|
412
678
|
* NonNullable<string | null | undefined> // string
|
|
413
679
|
* ```
|
|
414
680
|
*/
|
|
415
|
-
type NonNullable<T> = T & {};
|
|
681
|
+
type NonNullable$1<T> = T & {};
|
|
416
682
|
/**
|
|
417
683
|
* Exclusive properties (only one can be selected)
|
|
418
684
|
*
|
|
@@ -426,7 +692,7 @@ type Exclusive<T, K extends keyof T> = T extends unknown ? Omit<T, K> & { [P in
|
|
|
426
692
|
/**
|
|
427
693
|
* Remove null and undefined from all properties
|
|
428
694
|
*/
|
|
429
|
-
type NoNullish<T> = { [K in keyof T]: NonNullable<T[K]> };
|
|
695
|
+
type NoNullish<T> = { [K in keyof T]: NonNullable$1<T[K]> };
|
|
430
696
|
/**
|
|
431
697
|
* Make all properties optional while preserving undefined/null values
|
|
432
698
|
*/
|
|
@@ -544,4 +810,511 @@ type WritableKeys<T> = { [K in keyof T]: IfEquals<Readonly<Pick<T, K>>, Pick<T,
|
|
|
544
810
|
type ReadonlyKeys<T> = { [K in keyof T]: IfEquals<Readonly<Pick<T, K>>, Pick<T, K>, never, K> }[keyof T];
|
|
545
811
|
type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? A : B;
|
|
546
812
|
//#endregion
|
|
547
|
-
|
|
813
|
+
//#region src/keys/index.d.ts
|
|
814
|
+
/**
|
|
815
|
+
* Get all keys as literal union
|
|
816
|
+
*
|
|
817
|
+
* @example
|
|
818
|
+
* ```ts
|
|
819
|
+
* Keys<{ a: string; b: number }> // 'a' | 'b'
|
|
820
|
+
* ```
|
|
821
|
+
*/
|
|
822
|
+
type Keys<T> = keyof T;
|
|
823
|
+
/**
|
|
824
|
+
* Rename object keys based on a mapping
|
|
825
|
+
*
|
|
826
|
+
* @example
|
|
827
|
+
* ```ts
|
|
828
|
+
* RenameKeys<{ oldName: string }, { oldName: 'newName' }>
|
|
829
|
+
* // { newName: string }
|
|
830
|
+
* ```
|
|
831
|
+
*/
|
|
832
|
+
type RenameKeys<T, M extends Record<string, string>> = { [K in keyof T as K extends keyof M ? M[K] : K]: T[K] };
|
|
833
|
+
/**
|
|
834
|
+
* Prefix all keys with a string
|
|
835
|
+
*
|
|
836
|
+
* @example
|
|
837
|
+
* ```ts
|
|
838
|
+
* PrefixKeys<{ a: string; b: number }, 'data'>
|
|
839
|
+
* // { dataA: string; dataB: number }
|
|
840
|
+
* ```
|
|
841
|
+
*/
|
|
842
|
+
type PrefixKeys<T, P extends string> = { [K in keyof T as `${P}${Capitalize<K & string>}`]: T[K] };
|
|
843
|
+
/**
|
|
844
|
+
* Suffix all keys with a string
|
|
845
|
+
*
|
|
846
|
+
* @example
|
|
847
|
+
* ```ts
|
|
848
|
+
* SuffixKeys<{ a: string; b: number }, 'Data'>
|
|
849
|
+
* // { aData: string; bData: number }
|
|
850
|
+
* ```
|
|
851
|
+
*/
|
|
852
|
+
type SuffixKeys<T, S extends string> = { [K in keyof T as `${K & string}${S}`]: T[K] };
|
|
853
|
+
/**
|
|
854
|
+
* Convert keys to PascalCase
|
|
855
|
+
*
|
|
856
|
+
* @example
|
|
857
|
+
* ```ts
|
|
858
|
+
* PascalCaseKeys<{ helloWorld: string }>
|
|
859
|
+
* // { HelloWorld: string }
|
|
860
|
+
* ```
|
|
861
|
+
*/
|
|
862
|
+
type PascalCaseKeys<T> = { [K in keyof T as Capitalize<CamelCase<K & string>>]: T[K] };
|
|
863
|
+
/**
|
|
864
|
+
* Get keys by value type
|
|
865
|
+
*
|
|
866
|
+
* @example
|
|
867
|
+
* ```ts
|
|
868
|
+
* interface User {
|
|
869
|
+
* name: string
|
|
870
|
+
* age: number
|
|
871
|
+
* email: string
|
|
872
|
+
* }
|
|
873
|
+
*
|
|
874
|
+
* KeysByValueType<User, string> // 'name' | 'email'
|
|
875
|
+
* ```
|
|
876
|
+
*/
|
|
877
|
+
type KeysByValueType<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T];
|
|
878
|
+
/**
|
|
879
|
+
* Get keys that match a pattern
|
|
880
|
+
*
|
|
881
|
+
* @example
|
|
882
|
+
* ```ts
|
|
883
|
+
* interface User {
|
|
884
|
+
* userName: string
|
|
885
|
+
* userId: number
|
|
886
|
+
* userEmail: string
|
|
887
|
+
* age: number
|
|
888
|
+
* }
|
|
889
|
+
*
|
|
890
|
+
* FilterKeys<User, `user${string}`> // 'userName' | 'userId' | 'userEmail'
|
|
891
|
+
* ```
|
|
892
|
+
*/
|
|
893
|
+
type FilterKeys<T, P extends string> = keyof T extends infer K ? K extends P ? K : never : never;
|
|
894
|
+
//#endregion
|
|
895
|
+
//#region src/numeric/index.d.ts
|
|
896
|
+
/**
|
|
897
|
+
* Numeric type operations for compile-time arithmetic
|
|
898
|
+
*/
|
|
899
|
+
type NumberToArray<N extends number, Acc extends 0[] = []> = Acc['length'] extends N ? Acc : NumberToArray<N, [...Acc, 0]>;
|
|
900
|
+
/**
|
|
901
|
+
* Increment number type
|
|
902
|
+
*
|
|
903
|
+
* @example
|
|
904
|
+
* ```ts
|
|
905
|
+
* Inc<5> // 6
|
|
906
|
+
* Inc<0> // 1
|
|
907
|
+
* ```
|
|
908
|
+
*/
|
|
909
|
+
type Inc<N extends number> = [...NumberToArray<N>, 0]['length'];
|
|
910
|
+
/**
|
|
911
|
+
* Decrement number type
|
|
912
|
+
*
|
|
913
|
+
* @example
|
|
914
|
+
* ```ts
|
|
915
|
+
* Dec<5> // 4
|
|
916
|
+
* Dec<1> // 0
|
|
917
|
+
* Dec<0> // 0 (clamped)
|
|
918
|
+
* ```
|
|
919
|
+
*/
|
|
920
|
+
type Dec<N extends number> = N extends 0 ? 0 : NumberToArray<N> extends [0, ...infer Rest] ? Rest['length'] : 0;
|
|
921
|
+
/**
|
|
922
|
+
* Add two number types
|
|
923
|
+
*
|
|
924
|
+
* @example
|
|
925
|
+
* ```ts
|
|
926
|
+
* Add<3, 4> // 7
|
|
927
|
+
* Add<0, 5> // 5
|
|
928
|
+
* ```
|
|
929
|
+
*/
|
|
930
|
+
type Add<A extends number, B extends number> = [...NumberToArray<A>, ...NumberToArray<B>]['length'];
|
|
931
|
+
/**
|
|
932
|
+
* Subtract two number types
|
|
933
|
+
*
|
|
934
|
+
* @example
|
|
935
|
+
* ```ts
|
|
936
|
+
* Subtract<10, 3> // 7
|
|
937
|
+
* Subtract<5, 10> // 0 (clamped)
|
|
938
|
+
* ```
|
|
939
|
+
*/
|
|
940
|
+
type Subtract<A extends number, B extends number> = NumberToArray<B> extends [...number[], ...NumberToArray<A>] ? 0 : NumberToArray<A> extends [...NumberToArray<B>, ...infer Rest] ? Rest['length'] : 0;
|
|
941
|
+
/**
|
|
942
|
+
* Range of numbers from start to end (inclusive)
|
|
943
|
+
* Note: Limited to small ranges due to TypeScript recursion limits
|
|
944
|
+
*
|
|
945
|
+
* @example
|
|
946
|
+
* ```ts
|
|
947
|
+
* Range<1, 5> // 1 | 2 | 3 | 4 | 5
|
|
948
|
+
* Range<0, 3> // 0 | 1 | 2 | 3
|
|
949
|
+
* ```
|
|
950
|
+
*/
|
|
951
|
+
type Range<From extends number, To extends number, Acc extends number = From> = From extends To ? Acc : From extends To ? Acc : never;
|
|
952
|
+
/**
|
|
953
|
+
* Check if A is greater than B
|
|
954
|
+
*
|
|
955
|
+
* @example
|
|
956
|
+
* ```ts
|
|
957
|
+
* GreaterThan<5, 3> // true
|
|
958
|
+
* GreaterThan<3, 5> // false
|
|
959
|
+
* ```
|
|
960
|
+
*/
|
|
961
|
+
type GreaterThan<A extends number, B extends number> = Subtract<A, B> extends 0 ? false : true;
|
|
962
|
+
/**
|
|
963
|
+
* Check if A is less than B
|
|
964
|
+
*
|
|
965
|
+
* @example
|
|
966
|
+
* ```ts
|
|
967
|
+
* LessThan<3, 5> // true
|
|
968
|
+
* LessThan<5, 3> // false
|
|
969
|
+
* ```
|
|
970
|
+
*/
|
|
971
|
+
type LessThan<A extends number, B extends number> = Subtract<B, A> extends 0 ? false : true;
|
|
972
|
+
/**
|
|
973
|
+
* Maximum of two numbers
|
|
974
|
+
*
|
|
975
|
+
* @example
|
|
976
|
+
* ```ts
|
|
977
|
+
* Max<3, 5> // 5
|
|
978
|
+
* Max<5, 3> // 5
|
|
979
|
+
* ```
|
|
980
|
+
*/
|
|
981
|
+
type Max<A extends number, B extends number> = GreaterThan<A, B> extends true ? A : B;
|
|
982
|
+
/**
|
|
983
|
+
* Minimum of two numbers
|
|
984
|
+
*
|
|
985
|
+
* @example
|
|
986
|
+
* ```ts
|
|
987
|
+
* Min<3, 5> // 3
|
|
988
|
+
* Min<5, 3> // 3
|
|
989
|
+
* ```
|
|
990
|
+
*/
|
|
991
|
+
type Min<A extends number, B extends number> = LessThan<A, B> extends true ? A : B;
|
|
992
|
+
//#endregion
|
|
993
|
+
//#region src/path/index.d.ts
|
|
994
|
+
/**
|
|
995
|
+
* Enhanced path utilities with validation and array support
|
|
996
|
+
*/
|
|
997
|
+
type Primitive = string | number | boolean | null | undefined | symbol | bigint | Date | RegExp;
|
|
998
|
+
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
|
|
999
|
+
/**
|
|
1000
|
+
* Check if a path exists in type T
|
|
1001
|
+
*
|
|
1002
|
+
* @example
|
|
1003
|
+
* ```ts
|
|
1004
|
+
* interface Obj {
|
|
1005
|
+
* a: {
|
|
1006
|
+
* b: string
|
|
1007
|
+
* }
|
|
1008
|
+
* }
|
|
1009
|
+
*
|
|
1010
|
+
* ValidPath<Obj, 'a.b'> // true
|
|
1011
|
+
* ValidPath<Obj, 'a.c'> // false
|
|
1012
|
+
* ```
|
|
1013
|
+
*/
|
|
1014
|
+
type ValidPath<T, P extends string> = T extends Primitive ? P extends '' ? true : false : P extends '' ? true : P extends `${infer K}.${infer Rest}` ? K extends keyof T ? ValidPath<T[K], Rest> : false : P extends keyof T ? true : false;
|
|
1015
|
+
/**
|
|
1016
|
+
* Get all paths including array indices
|
|
1017
|
+
*
|
|
1018
|
+
* @example
|
|
1019
|
+
* ```ts
|
|
1020
|
+
* interface Users {
|
|
1021
|
+
* users: { name: string }[]
|
|
1022
|
+
* }
|
|
1023
|
+
*
|
|
1024
|
+
* ArrayPaths<Users>
|
|
1025
|
+
* // 'users' | `users.${number}` | `users.${number}.name`
|
|
1026
|
+
* ```
|
|
1027
|
+
*/
|
|
1028
|
+
type ArrayPaths<T, D extends number = 10> = [D] extends [never] ? never : T extends Primitive ? never : T extends readonly (infer E)[] ? ArrayPaths<E, Prev[D]> extends infer P ? P extends string ? `${number}` | `${number}.${P}` : `${number}` : `${number}` : { [K in keyof T]: T[K] extends readonly unknown[] ? `${K & string}` | `${K & string}.${ArrayPaths<T[K], Prev[D]>}` : T[K] extends Primitive ? `${K & string}` : `${K & string}` | `${K & string}.${ArrayPaths<T[K], Prev[D]>}` }[keyof T];
|
|
1029
|
+
/**
|
|
1030
|
+
* Get leaf node paths only (paths to primitive values)
|
|
1031
|
+
*
|
|
1032
|
+
* @example
|
|
1033
|
+
* ```ts
|
|
1034
|
+
* interface Users {
|
|
1035
|
+
* users: { name: string, age: number }[]
|
|
1036
|
+
* }
|
|
1037
|
+
*
|
|
1038
|
+
* LeafPaths<Users>
|
|
1039
|
+
* // `users.${number}.name` | `users.${number}.age`
|
|
1040
|
+
* ```
|
|
1041
|
+
*/
|
|
1042
|
+
type LeafPaths<T, D extends number = 10> = [D] extends [never] ? never : T extends Primitive ? never : T extends readonly (infer E)[] ? LeafPaths<E, Prev[D]> extends infer P ? P extends string ? `${number}.${P}` : never : never : { [K in keyof T]: T[K] extends Primitive ? `${K & string}` : LeafPaths<T[K], Prev[D]> extends never ? never : `${K & string}.${LeafPaths<T[K], Prev[D]>}` }[keyof T];
|
|
1043
|
+
/**
|
|
1044
|
+
* Get the length of a path (number of segments)
|
|
1045
|
+
*
|
|
1046
|
+
* @example
|
|
1047
|
+
* ```ts
|
|
1048
|
+
* PathLength<'a.b.c'> // 3
|
|
1049
|
+
* PathLength<'single'> // 1
|
|
1050
|
+
* ```
|
|
1051
|
+
*/
|
|
1052
|
+
type PathLength<P extends string> = P extends '' ? 0 : P extends `${string}.${infer Rest}` ? Increment<PathLength<Rest>> : 1;
|
|
1053
|
+
type Increment<N extends number, Arr extends 0[] = []> = N extends Arr['length'] ? [...Arr, 0]['length'] : Increment<N, [...Arr, 0]>;
|
|
1054
|
+
/**
|
|
1055
|
+
* Get the parent path of a given path
|
|
1056
|
+
*
|
|
1057
|
+
* @example
|
|
1058
|
+
* ```ts
|
|
1059
|
+
* ParentPath<'a.b.c'> // 'a.b'
|
|
1060
|
+
* ParentPath<'a'> // ''
|
|
1061
|
+
* ```
|
|
1062
|
+
*/
|
|
1063
|
+
type ParentPath<P extends string> = P extends `${infer Head}.${infer _}` ? Head : '';
|
|
1064
|
+
/**
|
|
1065
|
+
* Get the last segment of a path
|
|
1066
|
+
*
|
|
1067
|
+
* @example
|
|
1068
|
+
* ```ts
|
|
1069
|
+
* PathLeaf<'a.b.c'> // 'c'
|
|
1070
|
+
* PathLeaf<'a'> // 'a'
|
|
1071
|
+
* ```
|
|
1072
|
+
*/
|
|
1073
|
+
type PathLeaf<P extends string> = P extends `${string}.${infer Tail}` ? PathLeaf<Tail> : P;
|
|
1074
|
+
//#endregion
|
|
1075
|
+
//#region src/record/index.d.ts
|
|
1076
|
+
/**
|
|
1077
|
+
* Record and object manipulation types
|
|
1078
|
+
*/
|
|
1079
|
+
/**
|
|
1080
|
+
* Deep nullable - make all properties nullable
|
|
1081
|
+
*
|
|
1082
|
+
* @example
|
|
1083
|
+
* ```ts
|
|
1084
|
+
* DeepNullable<{ a: { b: string } }>
|
|
1085
|
+
* // { a: { b: string | null } }
|
|
1086
|
+
* ```
|
|
1087
|
+
*/
|
|
1088
|
+
type DeepNullable<T> = T extends ((...args: any[]) => any) ? T : T extends Map<infer K, infer V> ? Map<DeepNullable<K>, DeepNullable<V>> : T extends Set<infer V> ? Set<DeepNullable<V>> : T extends readonly (infer E)[] ? DeepNullable<E>[] : T extends object ? { [K in keyof T]: DeepNullable<T[K]> | null } : T | null;
|
|
1089
|
+
/**
|
|
1090
|
+
* Deep optional - make all properties optional
|
|
1091
|
+
*
|
|
1092
|
+
* @example
|
|
1093
|
+
* ```ts
|
|
1094
|
+
* DeepOptional<{ a: { b: string } }>
|
|
1095
|
+
* // { a?: { b?: string } }
|
|
1096
|
+
* ```
|
|
1097
|
+
*/
|
|
1098
|
+
type DeepOptional<T> = T extends ((...args: any[]) => any) ? T : T extends Map<infer K, infer V> ? Map<DeepOptional<K>, DeepOptional<V>> : T extends Set<infer V> ? Set<DeepOptional<V>> : T extends readonly (infer E)[] ? DeepOptional<E>[] : T extends object ? { [K in keyof T]?: DeepOptional<T[K]> } : T;
|
|
1099
|
+
/**
|
|
1100
|
+
* Immutable object - deep readonly alternative
|
|
1101
|
+
*
|
|
1102
|
+
* @example
|
|
1103
|
+
* ```ts
|
|
1104
|
+
* Immutable<{ a: { b: string[] } }>
|
|
1105
|
+
* // { readonly a: { readonly b: readonly string[] } }
|
|
1106
|
+
* ```
|
|
1107
|
+
*/
|
|
1108
|
+
type Immutable<T> = T extends ((...args: any[]) => any) ? T : T extends Map<infer K, infer V> ? ReadonlyMap<Immutable<K>, Immutable<V>> : T extends Set<infer V> ? ReadonlySet<Immutable<V>> : T extends readonly (infer E)[] ? readonly Immutable<E>[] : T extends object ? { readonly [K in keyof T]: Immutable<T[K]> } : T;
|
|
1109
|
+
/**
|
|
1110
|
+
* Mutable object - deep mutable alternative
|
|
1111
|
+
*
|
|
1112
|
+
* @example
|
|
1113
|
+
* ```ts
|
|
1114
|
+
* Mutable<{ readonly a: { readonly b: readonly string[] } }>
|
|
1115
|
+
* // { a: { b: string[] } }
|
|
1116
|
+
* ```
|
|
1117
|
+
*/
|
|
1118
|
+
type Mutable<T> = T extends ((...args: any[]) => any) ? T : T extends Map<infer K, infer V> ? Map<Mutable<K>, Mutable<V>> : T extends Set<infer V> ? Set<Mutable<V>> : T extends readonly (infer E)[] ? Mutable<E>[] : T extends object ? { -readonly [K in keyof T]: Mutable<T[K]> } : T;
|
|
1119
|
+
/**
|
|
1120
|
+
* Deep non-nullable - remove null and undefined from all properties
|
|
1121
|
+
*
|
|
1122
|
+
* @example
|
|
1123
|
+
* ```ts
|
|
1124
|
+
* DeepNonNullable<{ a: string | null; b: number | undefined }>
|
|
1125
|
+
* // { a: string; b: number }
|
|
1126
|
+
* ```
|
|
1127
|
+
*/
|
|
1128
|
+
type DeepNonNullable<T> = T extends ((...args: any[]) => any) ? T : T extends Map<infer K, infer V> ? Map<DeepNonNullable<K>, DeepNonNullable<V>> : T extends Set<infer V> ? Set<DeepNonNullable<V>> : T extends readonly (infer E)[] ? DeepNonNullable<E>[] : T extends object ? { [K in keyof T]: DeepNonNullable<NonNullable<T[K]>> } : NonNullable<T>;
|
|
1129
|
+
/**
|
|
1130
|
+
* Exact type - ensure object has exactly these keys
|
|
1131
|
+
*
|
|
1132
|
+
* @example
|
|
1133
|
+
* ```ts
|
|
1134
|
+
* Exact<{ a: string }, { a: string }> // { a: string }
|
|
1135
|
+
* Exact<{ a: string }, { a: string, b: number }> // never
|
|
1136
|
+
* ```
|
|
1137
|
+
*/
|
|
1138
|
+
type Exact<T, Shape> = T extends Shape ? Exclude<keyof T, keyof Shape> extends never ? T : never : never;
|
|
1139
|
+
/**
|
|
1140
|
+
* Make all properties non-optional
|
|
1141
|
+
*
|
|
1142
|
+
* @example
|
|
1143
|
+
* ```ts
|
|
1144
|
+
* Required<{ a?: string; b?: number }>
|
|
1145
|
+
* // { a: string; b: number }
|
|
1146
|
+
* ```
|
|
1147
|
+
*/
|
|
1148
|
+
type Required$1<T> = { [K in keyof T]-?: T[K] };
|
|
1149
|
+
/**
|
|
1150
|
+
* Deep required with null/undefined handling
|
|
1151
|
+
*
|
|
1152
|
+
* @example
|
|
1153
|
+
* ```ts
|
|
1154
|
+
* DeepRequired<{ a?: { b?: string } }>
|
|
1155
|
+
* // { a: { b: string } }
|
|
1156
|
+
* ```
|
|
1157
|
+
*/
|
|
1158
|
+
type DeepRequiredProperties<T> = T extends ((...args: any[]) => any) ? T : T extends Map<infer K, infer V> ? Map<DeepRequiredProperties<K>, DeepRequiredProperties<V>> : T extends Set<infer V> ? Set<DeepRequiredProperties<V>> : T extends readonly (infer E)[] ? DeepRequiredProperties<E>[] : T extends object ? { [K in keyof T]-?: DeepRequiredProperties<T[K]> } : T;
|
|
1159
|
+
/**
|
|
1160
|
+
* Object with at least the specified keys
|
|
1161
|
+
*
|
|
1162
|
+
* @example
|
|
1163
|
+
* ```ts
|
|
1164
|
+
* HasKeys<{ a: string; b: number }, 'a'>
|
|
1165
|
+
* // { a: string; b: number }
|
|
1166
|
+
* HasKeys<{ a: string }, 'b'>
|
|
1167
|
+
* // never
|
|
1168
|
+
* ```
|
|
1169
|
+
*/
|
|
1170
|
+
type HasKeys<T, K extends keyof any> = K extends keyof T ? T : never;
|
|
1171
|
+
/**
|
|
1172
|
+
* Object with exactly the specified keys
|
|
1173
|
+
*
|
|
1174
|
+
* @example
|
|
1175
|
+
* ```ts
|
|
1176
|
+
* HasExactKeys<{ a: string }, 'a'>
|
|
1177
|
+
* // true
|
|
1178
|
+
* HasExactKeys<{ a: string; b: number }, 'a'>
|
|
1179
|
+
* // false
|
|
1180
|
+
* ```
|
|
1181
|
+
*/
|
|
1182
|
+
type HasExactKeys<T, K extends keyof any> = keyof T extends K ? K extends keyof T ? true : false : false;
|
|
1183
|
+
//#endregion
|
|
1184
|
+
//#region src/template/index.d.ts
|
|
1185
|
+
/**
|
|
1186
|
+
* Template literal type utilities for string manipulation
|
|
1187
|
+
*/
|
|
1188
|
+
/**
|
|
1189
|
+
* Replace all occurrences of a substring
|
|
1190
|
+
*
|
|
1191
|
+
* @example
|
|
1192
|
+
* ```ts
|
|
1193
|
+
* ReplaceAll<'hello world world', 'world', 'there'> // 'hello there there'
|
|
1194
|
+
* ReplaceAll<'aaa', 'a', 'b'> // 'bbb'
|
|
1195
|
+
* ```
|
|
1196
|
+
*/
|
|
1197
|
+
type ReplaceAll<S extends string, From extends string, To extends string> = From extends '' ? S : S extends `${infer Before}${From}${infer After}` ? `${Before}${To}${ReplaceAll<After, From, To>}` : S;
|
|
1198
|
+
/**
|
|
1199
|
+
* Replace first occurrence of a substring
|
|
1200
|
+
*
|
|
1201
|
+
* @example
|
|
1202
|
+
* ```ts
|
|
1203
|
+
* Replace<'hello world world', 'world', 'there'> // 'hello there world'
|
|
1204
|
+
* ```
|
|
1205
|
+
*/
|
|
1206
|
+
type Replace<S extends string, From extends string, To extends string> = From extends '' ? S : S extends `${infer Before}${From}${infer After}` ? `${Before}${To}${After}` : S;
|
|
1207
|
+
/**
|
|
1208
|
+
* Trim whitespace from both ends
|
|
1209
|
+
*
|
|
1210
|
+
* @example
|
|
1211
|
+
* ```ts
|
|
1212
|
+
* Trim<' hello '> // 'hello'
|
|
1213
|
+
* Trim<'\n\ttext\n'> // 'text'
|
|
1214
|
+
* ```
|
|
1215
|
+
*/
|
|
1216
|
+
type Trim<S extends string> = TrimLeft<TrimRight<S>>;
|
|
1217
|
+
/**
|
|
1218
|
+
* Trim whitespace from left
|
|
1219
|
+
*
|
|
1220
|
+
* @example
|
|
1221
|
+
* ```ts
|
|
1222
|
+
* TrimLeft<' hello'> // 'hello'
|
|
1223
|
+
* ```
|
|
1224
|
+
*/
|
|
1225
|
+
type TrimLeft<S extends string> = S extends ` ${infer Rest}` ? TrimLeft<Rest> : S extends `\n${infer Rest}` ? TrimLeft<Rest> : S extends `\t${infer Rest}` ? TrimLeft<Rest> : S extends `\r${infer Rest}` ? TrimLeft<Rest> : S;
|
|
1226
|
+
/**
|
|
1227
|
+
* Trim whitespace from right
|
|
1228
|
+
*
|
|
1229
|
+
* @example
|
|
1230
|
+
* ```ts
|
|
1231
|
+
* TrimRight<'hello '> // 'hello'
|
|
1232
|
+
* ```
|
|
1233
|
+
*/
|
|
1234
|
+
type TrimRight<S extends string> = S extends `${infer Rest} ` ? TrimRight<Rest> : S extends `${infer Rest}\n` ? TrimRight<Rest> : S extends `${infer Rest}\t` ? TrimRight<Rest> : S extends `${infer Rest}\r` ? TrimRight<Rest> : S;
|
|
1235
|
+
/**
|
|
1236
|
+
* Convert string to array of characters
|
|
1237
|
+
*
|
|
1238
|
+
* @example
|
|
1239
|
+
* ```ts
|
|
1240
|
+
* StringToArray<'abc'> // ['a', 'b', 'c']
|
|
1241
|
+
* ```
|
|
1242
|
+
*/
|
|
1243
|
+
type StringToArray<S extends string, Acc extends string[] = []> = S extends `${infer First}${infer Rest}` ? StringToArray<Rest, [...Acc, First]> : Acc;
|
|
1244
|
+
/**
|
|
1245
|
+
* Capitalize all words in a string
|
|
1246
|
+
*
|
|
1247
|
+
* @example
|
|
1248
|
+
* ```ts
|
|
1249
|
+
* CapitalizeAll<'hello world'> // 'Hello World'
|
|
1250
|
+
* ```
|
|
1251
|
+
*/
|
|
1252
|
+
type CapitalizeAll<S extends string> = S extends `${infer First} ${infer Rest}` ? `${Capitalize<First>} ${CapitalizeAll<Rest>}` : S extends `${infer First}` ? Capitalize<First> : S;
|
|
1253
|
+
/**
|
|
1254
|
+
* Uncapitalize all words in a string
|
|
1255
|
+
*
|
|
1256
|
+
* @example
|
|
1257
|
+
* ```ts
|
|
1258
|
+
* UncapitalizeAll<'Hello World'> // 'hello world'
|
|
1259
|
+
* ```
|
|
1260
|
+
*/
|
|
1261
|
+
type UncapitalizeAll<S extends string> = S extends `${infer First} ${infer Rest}` ? `${Uncapitalize<First>} ${UncapitalizeAll<Rest>}` : S extends `${infer First}` ? Uncapitalize<First> : S;
|
|
1262
|
+
/**
|
|
1263
|
+
* Check if string starts with a prefix
|
|
1264
|
+
*
|
|
1265
|
+
* @example
|
|
1266
|
+
* ```ts
|
|
1267
|
+
* StartsWith<'hello world', 'hello'> // true
|
|
1268
|
+
* StartsWith<'hello world', 'world'> // false
|
|
1269
|
+
* ```
|
|
1270
|
+
*/
|
|
1271
|
+
type StartsWith<S extends string, P extends string> = S extends `${P}${any}` ? true : false;
|
|
1272
|
+
/**
|
|
1273
|
+
* Check if string ends with a suffix
|
|
1274
|
+
*
|
|
1275
|
+
* @example
|
|
1276
|
+
* ```ts
|
|
1277
|
+
* EndsWith<'hello world', 'world'> // true
|
|
1278
|
+
* EndsWith<'hello world', 'hello'> // false
|
|
1279
|
+
* ```
|
|
1280
|
+
*/
|
|
1281
|
+
type EndsWith<S extends string, P extends string> = S extends `${any}${P}` ? true : false;
|
|
1282
|
+
/**
|
|
1283
|
+
* Get string length at type level
|
|
1284
|
+
*
|
|
1285
|
+
* @example
|
|
1286
|
+
* ```ts
|
|
1287
|
+
* StringLength<'hello'> // 5
|
|
1288
|
+
* ```
|
|
1289
|
+
*/
|
|
1290
|
+
type StringLength<S extends string, Acc extends 0[] = []> = S extends `${string}${infer Rest}` ? StringLength<Rest, [...Acc, 0]> : Acc['length'];
|
|
1291
|
+
/**
|
|
1292
|
+
* Repeat a string N times
|
|
1293
|
+
*
|
|
1294
|
+
* @example
|
|
1295
|
+
* ```ts
|
|
1296
|
+
* Repeat<'ab', 3> // 'ababab'
|
|
1297
|
+
* ```
|
|
1298
|
+
*/
|
|
1299
|
+
type Repeat<S extends string, N extends number, Acc extends string = '', Count extends 0[] = []> = Count['length'] extends N ? Acc : Repeat<S, N, `${Acc}${S}`, [...Count, 0]>;
|
|
1300
|
+
/**
|
|
1301
|
+
* Pad string on the left
|
|
1302
|
+
*
|
|
1303
|
+
* @example
|
|
1304
|
+
* ```ts
|
|
1305
|
+
* PadStart<'5', 3, '0'> // '005'
|
|
1306
|
+
* ```
|
|
1307
|
+
*/
|
|
1308
|
+
type PadStart<S extends string, N extends number, P extends string = ' '> = StringLength<S> extends N ? S : N extends number ? `${P}${PadStart<S, Decrement<N>, P>}` : S;
|
|
1309
|
+
/**
|
|
1310
|
+
* Pad string on the right
|
|
1311
|
+
*
|
|
1312
|
+
* @example
|
|
1313
|
+
* ```ts
|
|
1314
|
+
* PadEnd<'5', 3, '0'> // '500'
|
|
1315
|
+
* ```
|
|
1316
|
+
*/
|
|
1317
|
+
type PadEnd<S extends string, N extends number, P extends string = ' '> = StringLength<S> extends N ? S : N extends number ? `${PadEnd<S, Decrement<N>, P>}${P}` : S;
|
|
1318
|
+
type Decrement<N extends number, Acc extends 0[] = []> = N extends 0 ? 0 : [...Acc, 0]['length'] extends N ? Acc['length'] : Decrement<N, [...Acc, 0]>;
|
|
1319
|
+
//#endregion
|
|
1320
|
+
export { Add, And, AppendParameter, ArrayElement, ArrayPaths, Assert, AsyncReturnType, AtLeastOne, Awaited, Brand, BrandedNumber, BrandedString, CamelCase, CamelCaseKeys, CapitalizeAll, DataOnly, Dec, DeepMutable, DeepNonNullable, DeepNullable, DeepOmit, DeepOmitPaths, DeepOptional, DeepPartial, DeepPick, DeepPickPaths, DeepReadonly, DeepRequired, DeepRequiredProperties, EndsWith, Exact, Exclusive, FilterKeys, FirstParameter, Flatten, FunctionKeys, FunctionOnly, GreaterThan, HasExactKeys, HasKeys, Head, If, Immutable, Inc, Init, IsAny, IsArray, IsAsyncFunction, IsEmptyTuple, IsEqual, IsFunction, IsNever, IsTuple, IsUnknown, Keys, KeysByValueType, Last, LeafPaths, LessThan, Literal, LiteralBoolean, LiteralNumber, LiteralString, LoosePartial, Max, Maybe, Merge, Min, Mutable, NoNullish, NonFunctionKeys, NonNullable$1 as NonNullable, Not, NthParameter, Nullable, OmitPartial, OmitRequired, OmitThisParameter, Optional, OptionalKeys, OptionalParameters, Or, PadEnd, PadStart, Parameters, ParentPath, PascalCaseKeys, PathLeaf, PathLength, PathValue, Paths, PickPartial, PickRequired, PrefixKeys, PrependParameter, Range, ReadonlyKeys, RenameKeys, Repeat, Replace, ReplaceAll, Required$1 as Required, RequiredKeys, ReturnType, Reverse, SnakeCase, SnakeCaseKeys, SplitPath, StartsWith, StrictExclude, StrictExtract, StringLength, StringToArray, Subtract, SuffixKeys, Tail$1 as Tail, ThisParameterType, Trim, TrimLeft, TrimRight, TupleLength, Unbrand, UncapitalizeAll, UnionToIntersection, UnionToTuple, ValidPath, ValueOf, WritableKeys };
|