@visulima/object 1.0.0 → 1.0.2

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/dist/index.d.cts CHANGED
@@ -166,6 +166,71 @@ fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface`
166
166
  */
167
167
  type Simplify<T> = {[KeyType in keyof T]: T[KeyType]} & {};
168
168
 
169
+ /**
170
+ Returns the static, fixed-length portion of the given array, excluding variable-length parts.
171
+
172
+ @example
173
+ ```
174
+ type A = [string, number, boolean, ...string[]];
175
+ type B = StaticPartOfArray<A>;
176
+ //=> [string, number, boolean]
177
+ ```
178
+ */
179
+ type StaticPartOfArray<T extends UnknownArray, Result extends UnknownArray = []> =
180
+ T extends unknown
181
+ ? number extends T['length'] ?
182
+ T extends readonly [infer U, ...infer V]
183
+ ? StaticPartOfArray<V, [...Result, U]>
184
+ : Result
185
+ : T
186
+ : never; // Should never happen
187
+
188
+ /**
189
+ Returns the variable, non-fixed-length portion of the given array, excluding static-length parts.
190
+
191
+ @example
192
+ ```
193
+ type A = [string, number, boolean, ...string[]];
194
+ type B = VariablePartOfArray<A>;
195
+ //=> string[]
196
+ ```
197
+ */
198
+ type VariablePartOfArray<T extends UnknownArray> =
199
+ T extends unknown
200
+ ? T extends readonly [...StaticPartOfArray<T>, ...infer U]
201
+ ? U
202
+ : []
203
+ : never; // Should never happen
204
+
205
+ /**
206
+ Set the given array to readonly if `IsReadonly` is `true`, otherwise set the given array to normal, then return the result.
207
+
208
+ @example
209
+ ```
210
+ type ReadonlyArray = readonly string[];
211
+ type NormalArray = string[];
212
+
213
+ type ReadonlyResult = SetArrayAccess<NormalArray, true>;
214
+ //=> readonly string[]
215
+
216
+ type NormalResult = SetArrayAccess<ReadonlyArray, false>;
217
+ //=> string[]
218
+ ```
219
+ */
220
+ type SetArrayAccess<T extends UnknownArray, IsReadonly extends boolean> =
221
+ T extends readonly [...infer U] ?
222
+ IsReadonly extends true
223
+ ? readonly [...U]
224
+ : [...U]
225
+ : T;
226
+
227
+ /**
228
+ Returns whether the given array `T` is readonly.
229
+ */
230
+ type IsArrayReadonly<T extends UnknownArray> = T extends unknown[] ? false : true;
231
+
232
+ type StringDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
233
+
169
234
  /**
170
235
  Returns a boolean for whether the given type is `any`.
171
236
 
@@ -255,6 +320,49 @@ type ShouldBeTrue = IsNegative<-1>;
255
320
  */
256
321
  type IsNegative<T extends Numeric> = T extends Negative<T> ? true : false;
257
322
 
323
+ /**
324
+ Returns a boolean for whether the given type is `never`.
325
+
326
+ @link https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919
327
+ @link https://stackoverflow.com/a/53984913/10292952
328
+ @link https://www.zhenghao.io/posts/ts-never
329
+
330
+ Useful in type utilities, such as checking if something does not occur.
331
+
332
+ @example
333
+ ```
334
+ import type {IsNever, And} from 'type-fest';
335
+
336
+ // https://github.com/andnp/SimplyTyped/blob/master/src/types/strings.ts
337
+ type AreStringsEqual<A extends string, B extends string> =
338
+ And<
339
+ IsNever<Exclude<A, B>> extends true ? true : false,
340
+ IsNever<Exclude<B, A>> extends true ? true : false
341
+ >;
342
+
343
+ type EndIfEqual<I extends string, O extends string> =
344
+ AreStringsEqual<I, O> extends true
345
+ ? never
346
+ : void;
347
+
348
+ function endIfEqual<I extends string, O extends string>(input: I, output: O): EndIfEqual<I, O> {
349
+ if (input === output) {
350
+ process.exit(0);
351
+ }
352
+ }
353
+
354
+ endIfEqual('abc', 'abc');
355
+ //=> never
356
+
357
+ endIfEqual('abc', '123');
358
+ //=> void
359
+ ```
360
+
361
+ @category Type Guard
362
+ @category Utilities
363
+ */
364
+ type IsNever<T> = [T] extends [never] ? true : false;
365
+
258
366
  /**
259
367
  Returns a boolean for whether two given types are both true.
260
368
 
@@ -391,49 +499,6 @@ type LessThan<A extends number, B extends number> = number extends A | B
391
499
  ? never
392
500
  : GreaterThanOrEqual<A, B> extends true ? false : true;
393
501
 
394
- /**
395
- Returns a boolean for whether the given type is `never`.
396
-
397
- @link https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919
398
- @link https://stackoverflow.com/a/53984913/10292952
399
- @link https://www.zhenghao.io/posts/ts-never
400
-
401
- Useful in type utilities, such as checking if something does not occur.
402
-
403
- @example
404
- ```
405
- import type {IsNever, And} from 'type-fest';
406
-
407
- // https://github.com/andnp/SimplyTyped/blob/master/src/types/strings.ts
408
- type AreStringsEqual<A extends string, B extends string> =
409
- And<
410
- IsNever<Exclude<A, B>> extends true ? true : false,
411
- IsNever<Exclude<B, A>> extends true ? true : false
412
- >;
413
-
414
- type EndIfEqual<I extends string, O extends string> =
415
- AreStringsEqual<I, O> extends true
416
- ? never
417
- : void;
418
-
419
- function endIfEqual<I extends string, O extends string>(input: I, output: O): EndIfEqual<I, O> {
420
- if (input === output) {
421
- process.exit(0);
422
- }
423
- }
424
-
425
- endIfEqual('abc', 'abc');
426
- //=> never
427
-
428
- endIfEqual('abc', '123');
429
- //=> void
430
- ```
431
-
432
- @category Type Guard
433
- @category Utilities
434
- */
435
- type IsNever<T> = [T] extends [never] ? true : false;
436
-
437
502
  /**
438
503
  Infer the length of the given tuple `<T>`.
439
504
 
@@ -473,45 +538,57 @@ type BuildTuple<L extends number, Fill = unknown, T extends readonly unknown[] =
473
538
  : BuildTuple<L, Fill, [...T, Fill]>;
474
539
 
475
540
  /**
476
- Create an object type with the given key `<Key>` and value `<Value>`.
541
+ Returns the maximum value from a tuple of integers.
477
542
 
478
- It will copy the prefix and optional status of the same key from the given object `CopiedFrom` into the result.
543
+ Note:
544
+ - Float numbers are not supported.
479
545
 
480
546
  @example
481
547
  ```
482
- type A = BuildObject<'a', string>;
483
- //=> {a: string}
548
+ ArrayMax<[1, 2, 5, 3]>;
549
+ //=> 5
484
550
 
485
- // Copy `readonly` and `?` from the key `a` of `{readonly a?: any}`
486
- type B = BuildObject<'a', string, {readonly a?: any}>;
487
- //=> {readonly a?: string}
551
+ ArrayMax<[1, 2, 5, 3, 99, -1]>;
552
+ //=> 99
488
553
  ```
489
554
  */
490
- type BuildObject<Key extends PropertyKey, Value, CopiedFrom extends object = {}> =
491
- Key extends keyof CopiedFrom
492
- ? Pick<{[_ in keyof CopiedFrom]: Value}, Key>
493
- : Key extends `${infer NumberKey extends number}`
494
- ? NumberKey extends keyof CopiedFrom
495
- ? Pick<{[_ in keyof CopiedFrom]: Value}, NumberKey>
496
- : {[_ in Key]: Value}
497
- : {[_ in Key]: Value};
555
+ type TupleMax<A extends number[], Result extends number = NegativeInfinity> = number extends A[number]
556
+ ? never :
557
+ A extends [infer F extends number, ...infer R extends number[]]
558
+ ? GreaterThan<F, Result> extends true
559
+ ? TupleMax<R, F>
560
+ : TupleMax<R, Result>
561
+ : Result;
498
562
 
499
563
  /**
500
- Return a string representation of the given string or number.
564
+ Returns the minimum value from a tuple of integers.
501
565
 
502
- Note: This type is not the return type of the `.toString()` function.
503
- */
504
- type ToString<T> = T extends string | number ? `${T}` : never;
566
+ Note:
567
+ - Float numbers are not supported.
505
568
 
506
- /**
507
- Matches any primitive, `void`, `Date`, or `RegExp` value.
569
+ @example
570
+ ```
571
+ ArrayMin<[1, 2, 5, 3]>;
572
+ //=> 1
573
+
574
+ ArrayMin<[1, 2, 5, 3, -5]>;
575
+ //=> -5
576
+ ```
508
577
  */
509
- type BuiltIns = Primitive | void | Date | RegExp;
578
+ type TupleMin<A extends number[], Result extends number = PositiveInfinity> = number extends A[number]
579
+ ? never
580
+ : A extends [infer F extends number, ...infer R extends number[]]
581
+ ? LessThan<F, Result> extends true
582
+ ? TupleMin<R, F>
583
+ : TupleMin<R, Result>
584
+ : Result;
510
585
 
511
586
  /**
512
- Matches non-recursive types.
587
+ Return a string representation of the given string or number.
588
+
589
+ Note: This type is not the return type of the `.toString()` function.
513
590
  */
514
- type NonRecursiveType = BuiltIns | Function | (new (...arguments_: any[]) => unknown);
591
+ type ToString<T> = T extends string | number ? `${T}` : never;
515
592
 
516
593
  /**
517
594
  Converts a numeric string to a number.
@@ -549,25 +626,6 @@ type StringToNumber<S extends string> = S extends `${infer N extends number}`
549
626
  ? NegativeInfinity
550
627
  : never;
551
628
 
552
- /**
553
- Returns the length of the given string.
554
-
555
- @example
556
- ```
557
- StringLength<'abcde'>;
558
- //=> 5
559
-
560
- StringLength<string>;
561
- //=> never
562
- ```
563
-
564
- @category String
565
- @category Template literal
566
- */
567
- type StringLength<S extends string> = string extends S
568
- ? never
569
- : StringToArray<S>['length'];
570
-
571
629
  /**
572
630
  Returns an array of the characters of the string.
573
631
 
@@ -588,86 +646,24 @@ type StringToArray<S extends string, Result extends string[] = []> = string exte
588
646
  ? StringToArray<R, [...Result, F]>
589
647
  : Result;
590
648
 
591
- type StringDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
592
-
593
- /**
594
- Extract the object field type if T is an object and K is a key of T, return `never` otherwise.
595
-
596
- It creates a type-safe way to access the member type of `unknown` type.
597
- */
598
- type ObjectValue<T, K> =
599
- K extends keyof T
600
- ? T[K]
601
- : ToString<K> extends keyof T
602
- ? T[ToString<K>]
603
- : K extends `${infer NumberK extends number}`
604
- ? NumberK extends keyof T
605
- ? T[NumberK]
606
- : never
607
- : never;
608
-
609
649
  /**
610
- Returns the maximum value from a tuple of integers.
611
-
612
- Note:
613
- - Float numbers are not supported.
650
+ Returns the length of the given string.
614
651
 
615
652
  @example
616
653
  ```
617
- ArrayMax<[1, 2, 5, 3]>;
654
+ StringLength<'abcde'>;
618
655
  //=> 5
619
656
 
620
- ArrayMax<[1, 2, 5, 3, 99, -1]>;
621
- //=> 99
622
- ```
623
- */
624
- type ArrayMax<A extends number[], Result extends number = NegativeInfinity> = number extends A[number]
625
- ? never :
626
- A extends [infer F extends number, ...infer R extends number[]]
627
- ? GreaterThan<F, Result> extends true
628
- ? ArrayMax<R, F>
629
- : ArrayMax<R, Result>
630
- : Result;
631
-
632
- /**
633
- Returns the minimum value from a tuple of integers.
634
-
635
- Note:
636
- - Float numbers are not supported.
637
-
638
- @example
657
+ StringLength<string>;
658
+ //=> never
639
659
  ```
640
- ArrayMin<[1, 2, 5, 3]>;
641
- //=> 1
642
660
 
643
- ArrayMin<[1, 2, 5, 3, -5]>;
644
- //=> -5
645
- ```
661
+ @category String
662
+ @category Template literal
646
663
  */
647
- type ArrayMin<A extends number[], Result extends number = PositiveInfinity> = number extends A[number]
664
+ type StringLength<S extends string> = string extends S
648
665
  ? never
649
- : A extends [infer F extends number, ...infer R extends number[]]
650
- ? LessThan<F, Result> extends true
651
- ? ArrayMin<R, F>
652
- : ArrayMin<R, Result>
653
- : Result;
654
-
655
- /**
656
- Returns the absolute value of a given value.
657
-
658
- @example
659
- ```
660
- NumberAbsolute<-1>;
661
- //=> 1
662
-
663
- NumberAbsolute<1>;
664
- //=> 1
665
-
666
- NumberAbsolute<NegativeInfinity>
667
- //=> PositiveInfinity
668
- ```
669
- */
670
- type NumberAbsolute<N extends number> = `${N}` extends `-${infer StringPositiveN}` ? StringToNumber<StringPositiveN> : N;
666
+ : StringToArray<S>['length'];
671
667
 
672
668
  /**
673
669
  Returns a boolean for whether `A` represents a number greater than `B`, where `A` and `B` are both numeric strings and have the same length.
@@ -737,40 +733,84 @@ type PositiveNumericCharacterGt<A extends string, B extends string> = NumericStr
737
733
  : never;
738
734
 
739
735
  /**
740
- Returns the static, fixed-length portion of the given array, excluding variable-length parts.
736
+ Get the exact version of the given `Key` in the given object `T`.
737
+
738
+ Use-case: You known that a number key (e.g. 10) is in an object, but you don't know how it is defined in the object, as a string or as a number (e.g. 10 or '10'). You can use this type to get the exact version of the key. See the example.
741
739
 
742
740
  @example
743
741
  ```
744
- type A = [string, number, boolean, ...string[]];
745
- type B = StaticPartOfArray<A>;
746
- //=> [string, number, boolean]
742
+ type Object = {
743
+ 0: number;
744
+ '1': string;
745
+ };
746
+
747
+ type Key1 = ExactKey<Object, '0'>;
748
+ //=> 0
749
+ type Key2 = ExactKey<Object, 0>;
750
+ //=> 0
751
+
752
+ type Key3 = ExactKey<Object, '1'>;
753
+ //=> '1'
754
+ type Key4 = ExactKey<Object, 1>;
755
+ //=> '1'
747
756
  ```
757
+
758
+ @category Object
748
759
  */
749
- type StaticPartOfArray<T extends UnknownArray, Result extends UnknownArray = []> =
750
- T extends unknown
751
- ? number extends T['length'] ?
752
- T extends readonly [infer U, ...infer V]
753
- ? StaticPartOfArray<V, [...Result, U]>
754
- : Result
755
- : T
756
- : never; // Should never happen
760
+ type ExactKey<T extends object, Key extends PropertyKey> =
761
+ Key extends keyof T
762
+ ? Key
763
+ : ToString<Key> extends keyof T
764
+ ? ToString<Key>
765
+ : Key extends `${infer NumberKey extends number}`
766
+ ? NumberKey extends keyof T
767
+ ? NumberKey
768
+ : never
769
+ : never;
770
+
771
+ /**
772
+ Returns the absolute value of a given value.
773
+
774
+ @example
775
+ ```
776
+ NumberAbsolute<-1>;
777
+ //=> 1
778
+
779
+ NumberAbsolute<1>;
780
+ //=> 1
781
+
782
+ NumberAbsolute<NegativeInfinity>
783
+ //=> PositiveInfinity
784
+ ```
785
+ */
786
+ type NumberAbsolute<N extends number> = `${N}` extends `-${infer StringPositiveN}` ? StringToNumber<StringPositiveN> : N;
757
787
 
758
788
  /**
759
- Returns the variable, non-fixed-length portion of the given array, excluding static-length parts.
789
+ Check whether the given type is a number or a number string.
790
+
791
+ Supports floating-point as a string.
760
792
 
761
793
  @example
762
794
  ```
763
- type A = [string, number, boolean, ...string[]];
764
- type B = VariablePartOfArray<A>;
765
- //=> string[]
766
- ```
795
+ type A = IsNumberLike<'1'>;
796
+ //=> true
797
+
798
+ type B = IsNumberLike<'-1.1'>;
799
+ //=> true
800
+
801
+ type C = IsNumberLike<1>;
802
+ //=> true
803
+
804
+ type D = IsNumberLike<'a'>;
805
+ //=> false
767
806
  */
768
- type VariablePartOfArray<T extends UnknownArray> =
769
- T extends unknown
770
- ? T extends readonly [...StaticPartOfArray<T>, ...infer U]
771
- ? U
772
- : []
773
- : never; // Should never happen
807
+ type IsNumberLike<N> =
808
+ N extends number ? true
809
+ : N extends `${number}`
810
+ ? true
811
+ : N extends `${number}.${number}`
812
+ ? true
813
+ : false;
774
814
 
775
815
  /**
776
816
  Returns the minimum number in the given union of numbers.
@@ -816,6 +856,16 @@ type InternalUnionMax<N extends number, T extends UnknownArray = []> =
816
856
  ? InternalUnionMax<Exclude<N, T['length']>, T>
817
857
  : InternalUnionMax<N, [...T, unknown]>;
818
858
 
859
+ /**
860
+ Matches any primitive, `void`, `Date`, or `RegExp` value.
861
+ */
862
+ type BuiltIns = Primitive | void | Date | RegExp;
863
+
864
+ /**
865
+ Matches non-recursive types.
866
+ */
867
+ type NonRecursiveType = BuiltIns | Function | (new (...arguments_: any[]) => unknown);
868
+
819
869
  /**
820
870
  Returns a boolean for whether the given type is a union type.
821
871
 
@@ -852,67 +902,44 @@ type InternalIsUnion<T, U = T> =
852
902
  : never; // Should never happen
853
903
 
854
904
  /**
855
- Set the given array to readonly if `IsReadonly` is `true`, otherwise set the given array to normal, then return the result.
905
+ Create an object type with the given key `<Key>` and value `<Value>`.
906
+
907
+ It will copy the prefix and optional status of the same key from the given object `CopiedFrom` into the result.
856
908
 
857
909
  @example
858
910
  ```
859
- type ReadonlyArray = readonly string[];
860
- type NormalArray = string[];
861
-
862
- type ReadonlyResult = SetArrayAccess<NormalArray, true>;
863
- //=> readonly string[]
911
+ type A = BuildObject<'a', string>;
912
+ //=> {a: string}
864
913
 
865
- type NormalResult = SetArrayAccess<ReadonlyArray, false>;
866
- //=> string[]
914
+ // Copy `readonly` and `?` from the key `a` of `{readonly a?: any}`
915
+ type B = BuildObject<'a', string, {readonly a?: any}>;
916
+ //=> {readonly a?: string}
867
917
  ```
868
918
  */
869
- type SetArrayAccess<T extends UnknownArray, IsReadonly extends boolean> =
870
- T extends readonly [...infer U] ?
871
- IsReadonly extends true
872
- ? readonly [...U]
873
- : [...U]
874
- : T;
875
-
876
- /**
877
- Returns whether the given array `T` is readonly.
878
- */
879
- type IsArrayReadonly<T extends UnknownArray> = T extends unknown[] ? false : true;
919
+ type BuildObject<Key extends PropertyKey, Value, CopiedFrom extends object = {}> =
920
+ Key extends keyof CopiedFrom
921
+ ? Pick<{[_ in keyof CopiedFrom]: Value}, Key>
922
+ : Key extends `${infer NumberKey extends number}`
923
+ ? NumberKey extends keyof CopiedFrom
924
+ ? Pick<{[_ in keyof CopiedFrom]: Value}, NumberKey>
925
+ : {[_ in Key]: Value}
926
+ : {[_ in Key]: Value};
880
927
 
881
928
  /**
882
- Get the exact version of the given `Key` in the given object `T`.
883
-
884
- Use-case: You known that a number key (e.g. 10) is in an object, but you don't know how it is defined in the object, as a string or as a number (e.g. 10 or '10'). You can use this type to get the exact version of the key. See the example.
885
-
886
- @example
887
- ```
888
- type Object = {
889
- 0: number;
890
- '1': string;
891
- };
892
-
893
- type Key1 = ExactKey<Object, '0'>;
894
- //=> 0
895
- type Key2 = ExactKey<Object, 0>;
896
- //=> 0
897
-
898
- type Key3 = ExactKey<Object, '1'>;
899
- //=> '1'
900
- type Key4 = ExactKey<Object, 1>;
901
- //=> '1'
902
- ```
929
+ Extract the object field type if T is an object and K is a key of T, return `never` otherwise.
903
930
 
904
- @category Object
931
+ It creates a type-safe way to access the member type of `unknown` type.
905
932
  */
906
- type ExactKey<T extends object, Key extends PropertyKey> =
907
- Key extends keyof T
908
- ? Key
909
- : ToString<Key> extends keyof T
910
- ? ToString<Key>
911
- : Key extends `${infer NumberKey extends number}`
912
- ? NumberKey extends keyof T
913
- ? NumberKey
914
- : never
915
- : never;
933
+ type ObjectValue<T, K> =
934
+ K extends keyof T
935
+ ? T[K]
936
+ : ToString<K> extends keyof T
937
+ ? T[ToString<K>]
938
+ : K extends `${infer NumberK extends number}`
939
+ ? NumberK extends keyof T
940
+ ? T[NumberK]
941
+ : never
942
+ : never;
916
943
 
917
944
  /**
918
945
  Deeply simplifies an object type.
@@ -1028,132 +1055,184 @@ type SimplifyDeep<Type, ExcludeType = never> =
1028
1055
  >;
1029
1056
 
1030
1057
  /**
1031
- Returns the difference between two numbers.
1058
+ Returns the sum of two numbers.
1032
1059
 
1033
1060
  Note:
1034
1061
  - A or B can only support `-999` ~ `999`.
1062
+ - A and B can only be small integers, less than 1000.
1035
1063
  - If the result is negative, you can only get `number`.
1036
1064
 
1037
1065
  @example
1038
1066
  ```
1039
- import type {Subtract} from 'type-fest';
1040
-
1041
- Subtract<333, 222>;
1042
- //=> 111
1067
+ import type {Sum} from 'type-fest';
1043
1068
 
1044
- Subtract<111, -222>;
1069
+ Sum<111, 222>;
1045
1070
  //=> 333
1046
1071
 
1047
- Subtract<-111, 222>;
1072
+ Sum<-111, 222>;
1073
+ //=> 111
1074
+
1075
+ Sum<111, -222>;
1048
1076
  //=> number
1049
1077
 
1050
- Subtract<PositiveInfinity, 9999>;
1078
+ Sum<PositiveInfinity, -9999>;
1051
1079
  //=> PositiveInfinity
1052
1080
 
1053
- Subtract<PositiveInfinity, PositiveInfinity>;
1081
+ Sum<PositiveInfinity, NegativeInfinity>;
1054
1082
  //=> number
1055
1083
  ```
1056
1084
 
1057
1085
  @category Numeric
1058
1086
  */
1059
1087
  // TODO: Support big integer and negative number.
1060
- type Subtract<A extends number, B extends number> = number extends A | B
1088
+ type Sum<A extends number, B extends number> = number extends A | B
1061
1089
  ? number
1062
1090
  : [
1063
1091
  IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>,
1064
1092
  IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity>,
1065
1093
  ] extends infer R extends [boolean, boolean, boolean, boolean]
1066
1094
  ? Or<
1067
- And<IsEqual<R[0], true>, IsEqual<R[2], false>>,
1068
- And<IsEqual<R[3], true>, IsEqual<R[1], false>>
1095
+ And<IsEqual<R[0], true>, IsEqual<R[3], false>>,
1096
+ And<IsEqual<R[2], true>, IsEqual<R[1], false>>
1069
1097
  > extends true
1070
1098
  ? PositiveInfinity
1071
1099
  : Or<
1072
- And<IsEqual<R[1], true>, IsEqual<R[3], false>>,
1073
- And<IsEqual<R[2], true>, IsEqual<R[0], false>>
1100
+ And<IsEqual<R[1], true>, IsEqual<R[2], false>>,
1101
+ And<IsEqual<R[3], true>, IsEqual<R[0], false>>
1074
1102
  > extends true
1075
1103
  ? NegativeInfinity
1076
1104
  : true extends R[number]
1077
1105
  ? number
1078
- : [IsNegative<A>, IsNegative<B>] extends infer R
1106
+ : ([IsNegative<A>, IsNegative<B>] extends infer R
1079
1107
  ? [false, false] extends R
1080
- ? BuildTuple<A> extends infer R
1081
- ? R extends [...BuildTuple<B>, ...infer R]
1082
- ? R['length']
1083
- : number
1084
- : never
1085
- : LessThan<A, B> extends true
1108
+ ? [...BuildTuple<A>, ...BuildTuple<B>]['length']
1109
+ : [true, true] extends R
1086
1110
  ? number
1087
- : [false, true] extends R
1088
- ? Sum<A, NumberAbsolute<B>>
1089
- : Subtract<NumberAbsolute<B>, NumberAbsolute<A>>
1090
- : never
1111
+ : TupleMax<[NumberAbsolute<A>, NumberAbsolute<B>]> extends infer Max_
1112
+ ? TupleMin<[NumberAbsolute<A>, NumberAbsolute<B>]> extends infer Min_ extends number
1113
+ ? Max_ extends A | B
1114
+ ? Subtract<Max_, Min_>
1115
+ : number
1116
+ : never
1117
+ : never
1118
+ : never) & number
1091
1119
  : never;
1092
1120
 
1093
1121
  /**
1094
- Returns the sum of two numbers.
1122
+ Returns the difference between two numbers.
1095
1123
 
1096
1124
  Note:
1097
1125
  - A or B can only support `-999` ~ `999`.
1098
- - A and B can only be small integers, less than 1000.
1099
1126
  - If the result is negative, you can only get `number`.
1100
1127
 
1101
1128
  @example
1102
1129
  ```
1103
- import type {Sum} from 'type-fest';
1104
-
1105
- Sum<111, 222>;
1106
- //=> 333
1130
+ import type {Subtract} from 'type-fest';
1107
1131
 
1108
- Sum<-111, 222>;
1132
+ Subtract<333, 222>;
1109
1133
  //=> 111
1110
1134
 
1111
- Sum<111, -222>;
1135
+ Subtract<111, -222>;
1136
+ //=> 333
1137
+
1138
+ Subtract<-111, 222>;
1112
1139
  //=> number
1113
1140
 
1114
- Sum<PositiveInfinity, -9999>;
1141
+ Subtract<PositiveInfinity, 9999>;
1115
1142
  //=> PositiveInfinity
1116
1143
 
1117
- Sum<PositiveInfinity, NegativeInfinity>;
1144
+ Subtract<PositiveInfinity, PositiveInfinity>;
1118
1145
  //=> number
1119
1146
  ```
1120
1147
 
1121
1148
  @category Numeric
1122
1149
  */
1123
1150
  // TODO: Support big integer and negative number.
1124
- type Sum<A extends number, B extends number> = number extends A | B
1151
+ type Subtract<A extends number, B extends number> = number extends A | B
1125
1152
  ? number
1126
1153
  : [
1127
1154
  IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>,
1128
1155
  IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity>,
1129
1156
  ] extends infer R extends [boolean, boolean, boolean, boolean]
1130
1157
  ? Or<
1131
- And<IsEqual<R[0], true>, IsEqual<R[3], false>>,
1132
- And<IsEqual<R[2], true>, IsEqual<R[1], false>>
1158
+ And<IsEqual<R[0], true>, IsEqual<R[2], false>>,
1159
+ And<IsEqual<R[3], true>, IsEqual<R[1], false>>
1133
1160
  > extends true
1134
1161
  ? PositiveInfinity
1135
1162
  : Or<
1136
- And<IsEqual<R[1], true>, IsEqual<R[2], false>>,
1137
- And<IsEqual<R[3], true>, IsEqual<R[0], false>>
1163
+ And<IsEqual<R[1], true>, IsEqual<R[3], false>>,
1164
+ And<IsEqual<R[2], true>, IsEqual<R[0], false>>
1138
1165
  > extends true
1139
1166
  ? NegativeInfinity
1140
1167
  : true extends R[number]
1141
1168
  ? number
1142
- : ([IsNegative<A>, IsNegative<B>] extends infer R
1169
+ : [IsNegative<A>, IsNegative<B>] extends infer R
1143
1170
  ? [false, false] extends R
1144
- ? [...BuildTuple<A>, ...BuildTuple<B>]['length']
1145
- : [true, true] extends R
1171
+ ? BuildTuple<A> extends infer R
1172
+ ? R extends [...BuildTuple<B>, ...infer R]
1173
+ ? R['length']
1174
+ : number
1175
+ : never
1176
+ : LessThan<A, B> extends true
1146
1177
  ? number
1147
- : ArrayMax<[NumberAbsolute<A>, NumberAbsolute<B>]> extends infer Max_
1148
- ? ArrayMin<[NumberAbsolute<A>, NumberAbsolute<B>]> extends infer Min_ extends number
1149
- ? Max_ extends A | B
1150
- ? Subtract<Max_, Min_>
1151
- : number
1152
- : never
1153
- : never
1154
- : never) & number
1178
+ : [false, true] extends R
1179
+ ? Sum<A, NumberAbsolute<B>>
1180
+ : Subtract<NumberAbsolute<B>, NumberAbsolute<A>>
1181
+ : never
1155
1182
  : never;
1156
1183
 
1184
+ /**
1185
+ Paths options.
1186
+
1187
+ @see {@link Paths}
1188
+ */
1189
+ type PathsOptions = {
1190
+ /**
1191
+ The maximum depth to recurse when searching for paths.
1192
+
1193
+ @default 10
1194
+ */
1195
+ maxRecursionDepth?: number;
1196
+
1197
+ /**
1198
+ Use bracket notation for array indices and numeric object keys.
1199
+
1200
+ @default false
1201
+
1202
+ @example
1203
+ ```
1204
+ type ArrayExample = {
1205
+ array: ['foo'];
1206
+ };
1207
+
1208
+ type A = Paths<ArrayExample, {bracketNotation: false}>;
1209
+ //=> 'array' | 'array.0'
1210
+
1211
+ type B = Paths<ArrayExample, {bracketNotation: true}>;
1212
+ //=> 'array' | 'array[0]'
1213
+ ```
1214
+
1215
+ @example
1216
+ ```
1217
+ type NumberKeyExample = {
1218
+ 1: ['foo'];
1219
+ };
1220
+
1221
+ type A = Paths<NumberKeyExample, {bracketNotation: false}>;
1222
+ //=> 1 | '1' | '1.0'
1223
+
1224
+ type B = Paths<NumberKeyExample, {bracketNotation: true}>;
1225
+ //=> '[1]' | '[1][0]'
1226
+ ```
1227
+ */
1228
+ bracketNotation?: boolean;
1229
+ };
1230
+
1231
+ type DefaultPathsOptions = {
1232
+ maxRecursionDepth: 10;
1233
+ bracketNotation: false;
1234
+ };
1235
+
1157
1236
  /**
1158
1237
  Generate a union of all possible paths to properties in the given object.
1159
1238
 
@@ -1195,9 +1274,14 @@ open('listB.1'); // TypeError. Because listB only has one element.
1195
1274
  @category Object
1196
1275
  @category Array
1197
1276
  */
1198
- type Paths<T> = Paths_<T>;
1277
+ type Paths<T, Options extends PathsOptions = {}> = _Paths<T, {
1278
+ // Set default maxRecursionDepth to 10
1279
+ maxRecursionDepth: Options['maxRecursionDepth'] extends number ? Options['maxRecursionDepth'] : DefaultPathsOptions['maxRecursionDepth'];
1280
+ // Set default bracketNotation to false
1281
+ bracketNotation: Options['bracketNotation'] extends boolean ? Options['bracketNotation'] : DefaultPathsOptions['bracketNotation'];
1282
+ }>;
1199
1283
 
1200
- type Paths_<T, Depth extends number = 0> =
1284
+ type _Paths<T, Options extends Required<PathsOptions>> =
1201
1285
  T extends NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
1202
1286
  ? never
1203
1287
  : IsAny<T> extends true
@@ -1205,32 +1289,61 @@ type Paths_<T, Depth extends number = 0> =
1205
1289
  : T extends UnknownArray
1206
1290
  ? number extends T['length']
1207
1291
  // We need to handle the fixed and non-fixed index part of the array separately.
1208
- ? InternalPaths<StaticPartOfArray<T>, Depth>
1209
- | InternalPaths<Array<VariablePartOfArray<T>[number]>, Depth>
1210
- : InternalPaths<T, Depth>
1292
+ ? InternalPaths<StaticPartOfArray<T>, Options>
1293
+ | InternalPaths<Array<VariablePartOfArray<T>[number]>, Options>
1294
+ : InternalPaths<T, Options>
1211
1295
  : T extends object
1212
- ? InternalPaths<T, Depth>
1296
+ ? InternalPaths<T, Options>
1213
1297
  : never;
1214
1298
 
1215
- type InternalPaths<_T, Depth extends number = 0, T = Required<_T>> =
1216
- T extends EmptyObject | readonly []
1217
- ? never
1218
- : {
1219
- [Key in keyof T]:
1220
- Key extends string | number // Limit `Key` to string or number.
1221
- // If `Key` is a number, return `Key | `${Key}``, because both `array[0]` and `array['0']` work.
1222
- ?
1223
- | Key
1224
- | ToString<Key>
1225
- | (
1226
- LessThan<Depth, 15> extends true // Limit the depth to prevent infinite recursion
1227
- ? IsNever<Paths_<T[Key], Sum<Depth, 1>>> extends false
1228
- ? `${Key}.${Paths_<T[Key], Sum<Depth, 1>>}`
1299
+ type InternalPaths<T, Options extends Required<PathsOptions>> =
1300
+ Options['maxRecursionDepth'] extends infer MaxDepth extends number
1301
+ ? Required<T> extends infer T
1302
+ ? T extends EmptyObject | readonly []
1303
+ ? never
1304
+ : {
1305
+ [Key in keyof T]:
1306
+ Key extends string | number // Limit `Key` to string or number.
1307
+ ? (
1308
+ Options['bracketNotation'] extends true
1309
+ ? IsNumberLike<Key> extends true
1310
+ ? `[${Key}]`
1311
+ : (Key | ToString<Key>)
1312
+ : never
1313
+ |
1314
+ Options['bracketNotation'] extends false
1315
+ // If `Key` is a number, return `Key | `${Key}``, because both `array[0]` and `array['0']` work.
1316
+ ? (Key | ToString<Key>)
1317
+ : never
1318
+ ) extends infer TranformedKey extends string | number ?
1319
+ // 1. If style is 'a[0].b' and 'Key' is a numberlike value like 3 or '3', transform 'Key' to `[${Key}]`, else to `${Key}` | Key
1320
+ // 2. If style is 'a.0.b', transform 'Key' to `${Key}` | Key
1321
+ | TranformedKey
1322
+ | (
1323
+ // Recursively generate paths for the current key
1324
+ GreaterThan<MaxDepth, 0> extends true // Limit the depth to prevent infinite recursion
1325
+ ? _Paths<T[Key], {bracketNotation: Options['bracketNotation']; maxRecursionDepth: Subtract<MaxDepth, 1>}> extends infer SubPath
1326
+ ? SubPath extends string | number
1327
+ ? (
1328
+ Options['bracketNotation'] extends true
1329
+ ? SubPath extends `[${any}]` | `[${any}]${string}`
1330
+ ? `${TranformedKey}${SubPath}` // If next node is number key like `[3]`, no need to add `.` before it.
1331
+ : `${TranformedKey}.${SubPath}`
1332
+ : never
1333
+ ) | (
1334
+ Options['bracketNotation'] extends false
1335
+ ? `${TranformedKey}.${SubPath}`
1336
+ : never
1337
+ )
1338
+ : never
1339
+ : never
1340
+ : never
1341
+ )
1229
1342
  : never
1230
1343
  : never
1231
- )
1232
- : never
1233
- }[keyof T & (T extends UnknownArray ? number : unknown)];
1344
+ }[keyof T & (T extends UnknownArray ? number : unknown)]
1345
+ : never
1346
+ : never;
1234
1347
 
1235
1348
  /**
1236
1349
  Convert a union type to an intersection type using [distributive conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
@@ -1530,6 +1643,8 @@ type ArraySplice<
1530
1643
  : never // Should never happen
1531
1644
  : never; // Should never happen
1532
1645
 
1646
+ type LiteralStringUnion<T> = LiteralUnion<T, string>;
1647
+
1533
1648
  /**
1534
1649
  Allows creating a union type by combining primitive types and literal types without sacrificing auto-completion in IDEs for the literal type part of the union.
1535
1650
 
@@ -1758,6 +1873,25 @@ type UsefulInfo = OmitDeep<Info, 'userInfo.uselessInfo'>;
1758
1873
  // userInfo: {
1759
1874
  // name: string;
1760
1875
  // };
1876
+ // };
1877
+
1878
+ // Supports removing multiple paths
1879
+ type Info1 = {
1880
+ userInfo: {
1881
+ name: string;
1882
+ uselessField: string;
1883
+ uselessInfo: {
1884
+ foo: string;
1885
+ };
1886
+ };
1887
+ };
1888
+
1889
+ type UsefulInfo1 = OmitDeep<Info1, 'userInfo.uselessInfo' | 'userInfo.uselessField'>;
1890
+ // type UsefulInfo1 = {
1891
+ // userInfo: {
1892
+ // name: string;
1893
+ // };
1894
+ // };
1761
1895
 
1762
1896
  // Supports array
1763
1897
  type A = OmitDeep<[1, 'foo', 2], 1>;
@@ -1930,7 +2064,7 @@ type GetOptions = {
1930
2064
  /**
1931
2065
  Like the `Get` type but receives an array of strings as a path parameter.
1932
2066
  */
1933
- type GetWithPath<BaseType, Keys extends readonly string[], Options extends GetOptions = {}> =
2067
+ type GetWithPath<BaseType, Keys, Options extends GetOptions = {}> =
1934
2068
  Keys extends readonly []
1935
2069
  ? BaseType
1936
2070
  : Keys extends readonly [infer Head, ...infer Tail]
@@ -2101,8 +2235,13 @@ Get<Record<string, string>, 'foo', {strict: true}> // => string
2101
2235
  @category Array
2102
2236
  @category Template literal
2103
2237
  */
2104
- type Get<BaseType, Path extends string | readonly string[], Options extends GetOptions = {}> =
2105
- GetWithPath<BaseType, Path extends string ? ToPath<Path> : Path, Options>;
2238
+ type Get<
2239
+ BaseType,
2240
+ Path extends
2241
+ | readonly string[]
2242
+ | LiteralStringUnion<ToString<Paths<BaseType, {bracketNotation: false}> | Paths<BaseType, {bracketNotation: true}>>>,
2243
+ Options extends GetOptions = {}> =
2244
+ GetWithPath<BaseType, Path extends string ? ToPath<Path> : Path, Options>;
2106
2245
 
2107
2246
  declare const omit: <T extends { [key in string]: unknown; }, K extends string>(object: T, keys: Paths<T>[]) => OmitDeep<T, K>;
2108
2247