@visulima/object 1.0.9 → 1.0.10
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/CHANGELOG.md +11 -0
- package/README.md +1 -0
- package/dist/index.cjs +9 -9
- package/dist/index.d.cts +357 -365
- package/dist/index.d.mts +357 -365
- package/dist/index.d.ts +357 -365
- package/dist/index.mjs +9 -9
- package/dist/packem_shared/{getProperty-BuSUBWTY.cjs → getProperty-W4y1P_8H.cjs} +4 -4
- package/dist/packem_shared/{getProperty-CqSBQFGO.mjs → getProperty-uiEqCe4m.mjs} +4 -4
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -452,6 +452,71 @@ type ShouldBeTrue = IsNegative<-1>;
|
|
|
452
452
|
*/
|
|
453
453
|
type IsNegative<T extends Numeric> = T extends Negative<T> ? true : false;
|
|
454
454
|
|
|
455
|
+
/**
|
|
456
|
+
Returns a boolean for whether the given type is a `string` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
|
|
457
|
+
|
|
458
|
+
Useful for:
|
|
459
|
+
- providing strongly-typed string manipulation functions
|
|
460
|
+
- constraining strings to be a string literal
|
|
461
|
+
- type utilities, such as when constructing parsers and ASTs
|
|
462
|
+
|
|
463
|
+
The implementation of this type is inspired by the trick mentioned in this [StackOverflow answer](https://stackoverflow.com/a/68261113/420747).
|
|
464
|
+
|
|
465
|
+
@example
|
|
466
|
+
```
|
|
467
|
+
import type {IsStringLiteral} from 'type-fest';
|
|
468
|
+
|
|
469
|
+
type CapitalizedString<T extends string> = IsStringLiteral<T> extends true ? Capitalize<T> : string;
|
|
470
|
+
|
|
471
|
+
// https://github.com/yankeeinlondon/native-dash/blob/master/src/capitalize.ts
|
|
472
|
+
function capitalize<T extends Readonly<string>>(input: T): CapitalizedString<T> {
|
|
473
|
+
return (input.slice(0, 1).toUpperCase() + input.slice(1)) as CapitalizedString<T>;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const output = capitalize('hello, world!');
|
|
477
|
+
//=> 'Hello, world!'
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
@example
|
|
481
|
+
```
|
|
482
|
+
// String types with infinite set of possible values return `false`.
|
|
483
|
+
|
|
484
|
+
import type {IsStringLiteral} from 'type-fest';
|
|
485
|
+
|
|
486
|
+
type AllUppercaseStrings = IsStringLiteral<Uppercase<string>>;
|
|
487
|
+
//=> false
|
|
488
|
+
|
|
489
|
+
type StringsStartingWithOn = IsStringLiteral<`on${string}`>;
|
|
490
|
+
//=> false
|
|
491
|
+
|
|
492
|
+
// This behaviour is particularly useful in string manipulation utilities, as infinite string types often require separate handling.
|
|
493
|
+
|
|
494
|
+
type Length<S extends string, Counter extends never[] = []> =
|
|
495
|
+
IsStringLiteral<S> extends false
|
|
496
|
+
? number // return `number` for infinite string types
|
|
497
|
+
: S extends `${string}${infer Tail}`
|
|
498
|
+
? Length<Tail, [...Counter, never]>
|
|
499
|
+
: Counter['length'];
|
|
500
|
+
|
|
501
|
+
type L1 = Length<Lowercase<string>>;
|
|
502
|
+
//=> number
|
|
503
|
+
|
|
504
|
+
type L2 = Length<`${number}`>;
|
|
505
|
+
//=> number
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
@category Type Guard
|
|
509
|
+
@category Utilities
|
|
510
|
+
*/
|
|
511
|
+
type IsStringLiteral<T> = IfNever<T, false,
|
|
512
|
+
// If `T` is an infinite string type (e.g., `on${string}`), `Record<T, never>` produces an index signature,
|
|
513
|
+
// and since `{}` extends index signatures, the result becomes `false`.
|
|
514
|
+
T extends string
|
|
515
|
+
? {} extends Record<T, never>
|
|
516
|
+
? false
|
|
517
|
+
: true
|
|
518
|
+
: false>;
|
|
519
|
+
|
|
455
520
|
/**
|
|
456
521
|
Returns a boolean for whether two given types are both true.
|
|
457
522
|
|
|
@@ -588,32 +653,7 @@ type LessThan<A extends number, B extends number> = number extends A | B
|
|
|
588
653
|
? never
|
|
589
654
|
: GreaterThanOrEqual<A, B> extends true ? false : true;
|
|
590
655
|
|
|
591
|
-
|
|
592
|
-
Infer the length of the given tuple `<T>`.
|
|
593
|
-
|
|
594
|
-
Returns `never` if the given type is an non-fixed-length array like `Array<string>`.
|
|
595
|
-
|
|
596
|
-
@example
|
|
597
|
-
```
|
|
598
|
-
type Tuple = TupleLength<[string, number, boolean]>;
|
|
599
|
-
//=> 3
|
|
600
|
-
|
|
601
|
-
type Array = TupleLength<string[]>;
|
|
602
|
-
//=> never
|
|
603
|
-
|
|
604
|
-
// Supports union types.
|
|
605
|
-
type Union = TupleLength<[] | [1, 2, 3] | Array<number>>;
|
|
606
|
-
//=> 1 | 3
|
|
607
|
-
```
|
|
608
|
-
*/
|
|
609
|
-
type TupleLength<T extends UnknownArray> =
|
|
610
|
-
// `extends unknown` is used to convert `T` (if `T` is a union type) to
|
|
611
|
-
// a [distributive conditionaltype](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types))
|
|
612
|
-
T extends unknown
|
|
613
|
-
? number extends T['length']
|
|
614
|
-
? never // Return never if the given type is an non-flexed-length array like `Array<string>`
|
|
615
|
-
: T['length']
|
|
616
|
-
: never; // Should never happen
|
|
656
|
+
// Should never happen
|
|
617
657
|
|
|
618
658
|
/**
|
|
619
659
|
Create a tuple type of the given length `<L>` and fill it with the given type `<Fill>`.
|
|
@@ -628,52 +668,6 @@ type BuildTuple<L extends number, Fill = unknown, T extends readonly unknown[] =
|
|
|
628
668
|
? T
|
|
629
669
|
: BuildTuple<L, Fill, [...T, Fill]>;
|
|
630
670
|
|
|
631
|
-
/**
|
|
632
|
-
Returns the maximum value from a tuple of integers.
|
|
633
|
-
|
|
634
|
-
Note:
|
|
635
|
-
- Float numbers are not supported.
|
|
636
|
-
|
|
637
|
-
@example
|
|
638
|
-
```
|
|
639
|
-
ArrayMax<[1, 2, 5, 3]>;
|
|
640
|
-
//=> 5
|
|
641
|
-
|
|
642
|
-
ArrayMax<[1, 2, 5, 3, 99, -1]>;
|
|
643
|
-
//=> 99
|
|
644
|
-
```
|
|
645
|
-
*/
|
|
646
|
-
type TupleMax<A extends number[], Result extends number = NegativeInfinity> = number extends A[number]
|
|
647
|
-
? never :
|
|
648
|
-
A extends [infer F extends number, ...infer R extends number[]]
|
|
649
|
-
? GreaterThan<F, Result> extends true
|
|
650
|
-
? TupleMax<R, F>
|
|
651
|
-
: TupleMax<R, Result>
|
|
652
|
-
: Result;
|
|
653
|
-
|
|
654
|
-
/**
|
|
655
|
-
Returns the minimum value from a tuple of integers.
|
|
656
|
-
|
|
657
|
-
Note:
|
|
658
|
-
- Float numbers are not supported.
|
|
659
|
-
|
|
660
|
-
@example
|
|
661
|
-
```
|
|
662
|
-
ArrayMin<[1, 2, 5, 3]>;
|
|
663
|
-
//=> 1
|
|
664
|
-
|
|
665
|
-
ArrayMin<[1, 2, 5, 3, -5]>;
|
|
666
|
-
//=> -5
|
|
667
|
-
```
|
|
668
|
-
*/
|
|
669
|
-
type TupleMin<A extends number[], Result extends number = PositiveInfinity> = number extends A[number]
|
|
670
|
-
? never
|
|
671
|
-
: A extends [infer F extends number, ...infer R extends number[]]
|
|
672
|
-
? LessThan<F, Result> extends true
|
|
673
|
-
? TupleMin<R, F>
|
|
674
|
-
: TupleMin<R, Result>
|
|
675
|
-
: Result;
|
|
676
|
-
|
|
677
671
|
/**
|
|
678
672
|
Return a string representation of the given string or number.
|
|
679
673
|
|
|
@@ -904,48 +898,30 @@ type IsNumberLike<N> =
|
|
|
904
898
|
: false;
|
|
905
899
|
|
|
906
900
|
/**
|
|
907
|
-
Returns the
|
|
908
|
-
|
|
909
|
-
Note: Just supports numbers from 0 to 999.
|
|
901
|
+
Returns the number with reversed sign.
|
|
910
902
|
|
|
911
903
|
@example
|
|
912
904
|
```
|
|
913
|
-
|
|
905
|
+
ReverseSign<-1>;
|
|
914
906
|
//=> 1
|
|
915
|
-
```
|
|
916
|
-
*/
|
|
917
|
-
type UnionMin<N extends number> = InternalUnionMin<N>;
|
|
918
|
-
|
|
919
|
-
/**
|
|
920
|
-
The actual implementation of `UnionMin`. It's private because it has some arguments that don't need to be exposed.
|
|
921
|
-
*/
|
|
922
|
-
type InternalUnionMin<N extends number, T extends UnknownArray = []> =
|
|
923
|
-
T['length'] extends N
|
|
924
|
-
? T['length']
|
|
925
|
-
: InternalUnionMin<N, [...T, unknown]>;
|
|
926
907
|
|
|
927
|
-
|
|
928
|
-
|
|
908
|
+
ReverseSign<1>;
|
|
909
|
+
//=> -1
|
|
929
910
|
|
|
930
|
-
|
|
911
|
+
ReverseSign<NegativeInfinity>
|
|
912
|
+
//=> PositiveInfinity
|
|
931
913
|
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
type A = UnionMax<1 | 3 | 2>;
|
|
935
|
-
//=> 3
|
|
914
|
+
ReverseSign<PositiveInfinity>
|
|
915
|
+
//=> NegativeInfinity
|
|
936
916
|
```
|
|
937
917
|
*/
|
|
938
|
-
type
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
? T['length']
|
|
946
|
-
: T['length'] extends N
|
|
947
|
-
? InternalUnionMax<Exclude<N, T['length']>, T>
|
|
948
|
-
: InternalUnionMax<N, [...T, unknown]>;
|
|
918
|
+
type ReverseSign<N extends number> =
|
|
919
|
+
// Handle edge cases
|
|
920
|
+
N extends 0 ? 0 : N extends PositiveInfinity ? NegativeInfinity : N extends NegativeInfinity ? PositiveInfinity :
|
|
921
|
+
// Handle negative numbers
|
|
922
|
+
`${N}` extends `-${infer P extends number}` ? P
|
|
923
|
+
// Handle positive numbers
|
|
924
|
+
: `-${N}` extends `${infer R extends number}` ? R : never;
|
|
949
925
|
|
|
950
926
|
/**
|
|
951
927
|
Matches any primitive, `void`, `Date`, or `RegExp` value.
|
|
@@ -957,6 +933,24 @@ Matches non-recursive types.
|
|
|
957
933
|
*/
|
|
958
934
|
type NonRecursiveType = BuiltIns | Function | (new (...arguments_: any[]) => unknown);
|
|
959
935
|
|
|
936
|
+
/**
|
|
937
|
+
Returns a boolean for whether A is false.
|
|
938
|
+
|
|
939
|
+
@example
|
|
940
|
+
```
|
|
941
|
+
Not<true>;
|
|
942
|
+
//=> false
|
|
943
|
+
|
|
944
|
+
Not<false>;
|
|
945
|
+
//=> true
|
|
946
|
+
```
|
|
947
|
+
*/
|
|
948
|
+
type Not<A extends boolean> = A extends true
|
|
949
|
+
? false
|
|
950
|
+
: A extends false
|
|
951
|
+
? true
|
|
952
|
+
: never;
|
|
953
|
+
|
|
960
954
|
/**
|
|
961
955
|
Create an object type with the given key `<Key>` and value `<Value>`.
|
|
962
956
|
|
|
@@ -1110,76 +1104,11 @@ type SimplifyDeep<Type, ExcludeType = never> =
|
|
|
1110
1104
|
object
|
|
1111
1105
|
>;
|
|
1112
1106
|
|
|
1113
|
-
/**
|
|
1114
|
-
Returns the sum of two numbers.
|
|
1115
|
-
|
|
1116
|
-
Note:
|
|
1117
|
-
- A or B can only support `-999` ~ `999`.
|
|
1118
|
-
- A and B can only be small integers, less than 1000.
|
|
1119
|
-
- If the result is negative, you can only get `number`.
|
|
1120
|
-
|
|
1121
|
-
@example
|
|
1122
|
-
```
|
|
1123
|
-
import type {Sum} from 'type-fest';
|
|
1124
|
-
|
|
1125
|
-
Sum<111, 222>;
|
|
1126
|
-
//=> 333
|
|
1127
|
-
|
|
1128
|
-
Sum<-111, 222>;
|
|
1129
|
-
//=> 111
|
|
1130
|
-
|
|
1131
|
-
Sum<111, -222>;
|
|
1132
|
-
//=> number
|
|
1133
|
-
|
|
1134
|
-
Sum<PositiveInfinity, -9999>;
|
|
1135
|
-
//=> PositiveInfinity
|
|
1136
|
-
|
|
1137
|
-
Sum<PositiveInfinity, NegativeInfinity>;
|
|
1138
|
-
//=> number
|
|
1139
|
-
```
|
|
1140
|
-
|
|
1141
|
-
@category Numeric
|
|
1142
|
-
*/
|
|
1143
|
-
// TODO: Support big integer and negative number.
|
|
1144
|
-
type Sum<A extends number, B extends number> = number extends A | B
|
|
1145
|
-
? number
|
|
1146
|
-
: [
|
|
1147
|
-
IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>,
|
|
1148
|
-
IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity>,
|
|
1149
|
-
] extends infer R extends [boolean, boolean, boolean, boolean]
|
|
1150
|
-
? Or<
|
|
1151
|
-
And<IsEqual<R[0], true>, IsEqual<R[3], false>>,
|
|
1152
|
-
And<IsEqual<R[2], true>, IsEqual<R[1], false>>
|
|
1153
|
-
> extends true
|
|
1154
|
-
? PositiveInfinity
|
|
1155
|
-
: Or<
|
|
1156
|
-
And<IsEqual<R[1], true>, IsEqual<R[2], false>>,
|
|
1157
|
-
And<IsEqual<R[3], true>, IsEqual<R[0], false>>
|
|
1158
|
-
> extends true
|
|
1159
|
-
? NegativeInfinity
|
|
1160
|
-
: true extends R[number]
|
|
1161
|
-
? number
|
|
1162
|
-
: ([IsNegative<A>, IsNegative<B>] extends infer R
|
|
1163
|
-
? [false, false] extends R
|
|
1164
|
-
? [...BuildTuple<A>, ...BuildTuple<B>]['length']
|
|
1165
|
-
: [true, true] extends R
|
|
1166
|
-
? number
|
|
1167
|
-
: TupleMax<[NumberAbsolute<A>, NumberAbsolute<B>]> extends infer Max_
|
|
1168
|
-
? TupleMin<[NumberAbsolute<A>, NumberAbsolute<B>]> extends infer Min_ extends number
|
|
1169
|
-
? Max_ extends A | B
|
|
1170
|
-
? Subtract<Max_, Min_>
|
|
1171
|
-
: number
|
|
1172
|
-
: never
|
|
1173
|
-
: never
|
|
1174
|
-
: never) & number
|
|
1175
|
-
: never;
|
|
1176
|
-
|
|
1177
1107
|
/**
|
|
1178
1108
|
Returns the difference between two numbers.
|
|
1179
1109
|
|
|
1180
1110
|
Note:
|
|
1181
1111
|
- A or B can only support `-999` ~ `999`.
|
|
1182
|
-
- If the result is negative, you can only get `number`.
|
|
1183
1112
|
|
|
1184
1113
|
@example
|
|
1185
1114
|
```
|
|
@@ -1192,7 +1121,10 @@ Subtract<111, -222>;
|
|
|
1192
1121
|
//=> 333
|
|
1193
1122
|
|
|
1194
1123
|
Subtract<-111, 222>;
|
|
1195
|
-
//=>
|
|
1124
|
+
//=> -333
|
|
1125
|
+
|
|
1126
|
+
Subtract<18, 96>;
|
|
1127
|
+
//=> -78
|
|
1196
1128
|
|
|
1197
1129
|
Subtract<PositiveInfinity, 9999>;
|
|
1198
1130
|
//=> PositiveInfinity
|
|
@@ -1203,38 +1135,53 @@ Subtract<PositiveInfinity, PositiveInfinity>;
|
|
|
1203
1135
|
|
|
1204
1136
|
@category Numeric
|
|
1205
1137
|
*/
|
|
1206
|
-
// TODO: Support big integer
|
|
1207
|
-
type Subtract<A extends number, B extends number> =
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1138
|
+
// TODO: Support big integer.
|
|
1139
|
+
type Subtract<A extends number, B extends number> =
|
|
1140
|
+
// Handle cases when A or B is the actual "number" type
|
|
1141
|
+
number extends A | B ? number
|
|
1142
|
+
// Handle cases when A and B are both +/- infinity
|
|
1143
|
+
: A extends B & (PositiveInfinity | NegativeInfinity) ? number
|
|
1144
|
+
// Handle cases when A is - infinity or B is + infinity
|
|
1145
|
+
: A extends NegativeInfinity ? NegativeInfinity : B extends PositiveInfinity ? NegativeInfinity
|
|
1146
|
+
// Handle cases when A is + infinity or B is - infinity
|
|
1147
|
+
: A extends PositiveInfinity ? PositiveInfinity : B extends NegativeInfinity ? PositiveInfinity
|
|
1148
|
+
// Handle case when numbers are equal to each other
|
|
1149
|
+
: A extends B ? 0
|
|
1150
|
+
// Handle cases when A or B is 0
|
|
1151
|
+
: A extends 0 ? ReverseSign<B> : B extends 0 ? A
|
|
1152
|
+
// Handle remaining regular cases
|
|
1153
|
+
: SubtractPostChecks<A, B>;
|
|
1154
|
+
|
|
1155
|
+
/**
|
|
1156
|
+
Subtracts two numbers A and B, such that they are not equal and neither of them are 0, +/- infinity or the `number` type
|
|
1157
|
+
*/
|
|
1158
|
+
type SubtractPostChecks<A extends number, B extends number, AreNegative = [IsNegative<A>, IsNegative<B>]> =
|
|
1159
|
+
AreNegative extends [false, false]
|
|
1160
|
+
? SubtractPositives<A, B>
|
|
1161
|
+
: AreNegative extends [true, true]
|
|
1162
|
+
// When both numbers are negative we subtract the absolute values and then reverse the sign
|
|
1163
|
+
? ReverseSign<SubtractPositives<NumberAbsolute<A>, NumberAbsolute<B>>>
|
|
1164
|
+
// When the signs are different we can add the absolute values and then reverse the sign if A < B
|
|
1165
|
+
: [...BuildTuple<NumberAbsolute<A>>, ...BuildTuple<NumberAbsolute<B>>] extends infer R extends unknown[]
|
|
1166
|
+
? LessThan<A, B> extends true ? ReverseSign<R['length']> : R['length']
|
|
1167
|
+
: never;
|
|
1168
|
+
|
|
1169
|
+
/**
|
|
1170
|
+
Subtracts two positive numbers.
|
|
1171
|
+
*/
|
|
1172
|
+
type SubtractPositives<A extends number, B extends number> =
|
|
1173
|
+
LessThan<A, B> extends true
|
|
1174
|
+
// When A < B we can reverse the result of B - A
|
|
1175
|
+
? ReverseSign<SubtractIfAGreaterThanB<B, A>>
|
|
1176
|
+
: SubtractIfAGreaterThanB<A, B>;
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
Subtracts two positive numbers A and B such that A > B.
|
|
1180
|
+
*/
|
|
1181
|
+
type SubtractIfAGreaterThanB<A extends number, B extends number> =
|
|
1182
|
+
// This is where we always want to end up and do the actual subtraction
|
|
1183
|
+
BuildTuple<A> extends [...BuildTuple<B>, ...infer R]
|
|
1184
|
+
? R['length']
|
|
1238
1185
|
: never;
|
|
1239
1186
|
|
|
1240
1187
|
/**
|
|
@@ -1282,11 +1229,89 @@ type PathsOptions = {
|
|
|
1282
1229
|
```
|
|
1283
1230
|
*/
|
|
1284
1231
|
bracketNotation?: boolean;
|
|
1232
|
+
|
|
1233
|
+
/**
|
|
1234
|
+
Only include leaf paths in the output.
|
|
1235
|
+
|
|
1236
|
+
@default false
|
|
1237
|
+
|
|
1238
|
+
@example
|
|
1239
|
+
```
|
|
1240
|
+
type Post = {
|
|
1241
|
+
id: number;
|
|
1242
|
+
author: {
|
|
1243
|
+
id: number;
|
|
1244
|
+
name: {
|
|
1245
|
+
first: string;
|
|
1246
|
+
last: string;
|
|
1247
|
+
};
|
|
1248
|
+
};
|
|
1249
|
+
};
|
|
1250
|
+
|
|
1251
|
+
type AllPaths = Paths<Post, {leavesOnly: false}>;
|
|
1252
|
+
//=> 'id' | 'author' | 'author.id' | 'author.name' | 'author.name.first' | 'author.name.last'
|
|
1253
|
+
|
|
1254
|
+
type LeafPaths = Paths<Post, {leavesOnly: true}>;
|
|
1255
|
+
//=> 'id' | 'author.id' | 'author.name.first' | 'author.name.last'
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
@example
|
|
1259
|
+
```
|
|
1260
|
+
type ArrayExample = {
|
|
1261
|
+
array: Array<{foo: string}>;
|
|
1262
|
+
tuple: [string, {bar: string}];
|
|
1263
|
+
};
|
|
1264
|
+
|
|
1265
|
+
type AllPaths = Paths<ArrayExample, {leavesOnly: false}>;
|
|
1266
|
+
//=> 'array' | `array.${number}` | `array.${number}.foo` | 'tuple' | 'tuple.0' | 'tuple.1' | 'tuple.1.bar'
|
|
1267
|
+
|
|
1268
|
+
type LeafPaths = Paths<ArrayExample, {leavesOnly: true}>;
|
|
1269
|
+
//=> `array.${number}.foo` | 'tuple.0' | 'tuple.1.bar'
|
|
1270
|
+
```
|
|
1271
|
+
*/
|
|
1272
|
+
leavesOnly?: boolean;
|
|
1273
|
+
|
|
1274
|
+
/**
|
|
1275
|
+
Only include paths at the specified depth. By default all paths up to {@link PathsOptions.maxRecursionDepth | `maxRecursionDepth`} are included.
|
|
1276
|
+
|
|
1277
|
+
Note: Depth starts at `0` for root properties.
|
|
1278
|
+
|
|
1279
|
+
@default number
|
|
1280
|
+
|
|
1281
|
+
@example
|
|
1282
|
+
```
|
|
1283
|
+
type Post = {
|
|
1284
|
+
id: number;
|
|
1285
|
+
author: {
|
|
1286
|
+
id: number;
|
|
1287
|
+
name: {
|
|
1288
|
+
first: string;
|
|
1289
|
+
last: string;
|
|
1290
|
+
};
|
|
1291
|
+
};
|
|
1292
|
+
};
|
|
1293
|
+
|
|
1294
|
+
type DepthZero = Paths<Post, {depth: 0}>;
|
|
1295
|
+
//=> 'id' | 'author'
|
|
1296
|
+
|
|
1297
|
+
type DepthOne = Paths<Post, {depth: 1}>;
|
|
1298
|
+
//=> 'author.id' | 'author.name'
|
|
1299
|
+
|
|
1300
|
+
type DepthTwo = Paths<Post, {depth: 2}>;
|
|
1301
|
+
//=> 'author.name.first' | 'author.name.last'
|
|
1302
|
+
|
|
1303
|
+
type LeavesAtDepthOne = Paths<Post, {leavesOnly: true; depth: 1}>;
|
|
1304
|
+
//=> 'author.id'
|
|
1305
|
+
```
|
|
1306
|
+
*/
|
|
1307
|
+
depth?: number;
|
|
1285
1308
|
};
|
|
1286
1309
|
|
|
1287
1310
|
type DefaultPathsOptions = {
|
|
1288
1311
|
maxRecursionDepth: 10;
|
|
1289
1312
|
bracketNotation: false;
|
|
1313
|
+
leavesOnly: false;
|
|
1314
|
+
depth: number;
|
|
1290
1315
|
};
|
|
1291
1316
|
|
|
1292
1317
|
/**
|
|
@@ -1335,6 +1360,10 @@ type Paths<T, Options extends PathsOptions = {}> = _Paths<T, {
|
|
|
1335
1360
|
maxRecursionDepth: Options['maxRecursionDepth'] extends number ? Options['maxRecursionDepth'] : DefaultPathsOptions['maxRecursionDepth'];
|
|
1336
1361
|
// Set default bracketNotation to false
|
|
1337
1362
|
bracketNotation: Options['bracketNotation'] extends boolean ? Options['bracketNotation'] : DefaultPathsOptions['bracketNotation'];
|
|
1363
|
+
// Set default leavesOnly to false
|
|
1364
|
+
leavesOnly: Options['leavesOnly'] extends boolean ? Options['leavesOnly'] : DefaultPathsOptions['leavesOnly'];
|
|
1365
|
+
// Set default depth to number
|
|
1366
|
+
depth: Options['depth'] extends number ? Options['depth'] : DefaultPathsOptions['depth'];
|
|
1338
1367
|
}>;
|
|
1339
1368
|
|
|
1340
1369
|
type _Paths<T, Options extends Required<PathsOptions>> =
|
|
@@ -1374,11 +1403,30 @@ type InternalPaths<T, Options extends Required<PathsOptions>> =
|
|
|
1374
1403
|
) extends infer TranformedKey extends string | number ?
|
|
1375
1404
|
// 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
|
|
1376
1405
|
// 2. If style is 'a.0.b', transform 'Key' to `${Key}` | Key
|
|
1377
|
-
|
|
|
1406
|
+
| ((Options['leavesOnly'] extends true
|
|
1407
|
+
? MaxDepth extends 0
|
|
1408
|
+
? TranformedKey
|
|
1409
|
+
: T[Key] extends EmptyObject | readonly [] | NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
|
|
1410
|
+
? TranformedKey
|
|
1411
|
+
: never
|
|
1412
|
+
: TranformedKey
|
|
1413
|
+
) extends infer _TransformedKey
|
|
1414
|
+
// If `depth` is provided, the condition becomes truthy only when it reaches `0`.
|
|
1415
|
+
// Otherwise, since `depth` defaults to `number`, the condition is always truthy, returning paths at all depths.
|
|
1416
|
+
? 0 extends Options['depth']
|
|
1417
|
+
? _TransformedKey
|
|
1418
|
+
: never
|
|
1419
|
+
: never)
|
|
1378
1420
|
| (
|
|
1379
1421
|
// Recursively generate paths for the current key
|
|
1380
1422
|
GreaterThan<MaxDepth, 0> extends true // Limit the depth to prevent infinite recursion
|
|
1381
|
-
? _Paths<T[Key],
|
|
1423
|
+
? _Paths<T[Key],
|
|
1424
|
+
{
|
|
1425
|
+
bracketNotation: Options['bracketNotation'];
|
|
1426
|
+
maxRecursionDepth: Subtract<MaxDepth, 1>;
|
|
1427
|
+
leavesOnly: Options['leavesOnly'];
|
|
1428
|
+
depth: Subtract<Options['depth'], 1>;
|
|
1429
|
+
}> extends infer SubPath
|
|
1382
1430
|
? SubPath extends string | number
|
|
1383
1431
|
? (
|
|
1384
1432
|
Options['bracketNotation'] extends true
|
|
@@ -1562,7 +1610,9 @@ The implementation of `SplitArrayByIndex` for variable length arrays.
|
|
|
1562
1610
|
type SplitVariableArrayByIndex<T extends UnknownArray,
|
|
1563
1611
|
SplitIndex extends number,
|
|
1564
1612
|
T1 = Subtract<SplitIndex, StaticPartOfArray<T>['length']>,
|
|
1565
|
-
T2 = T1 extends number
|
|
1613
|
+
T2 = T1 extends number
|
|
1614
|
+
? BuildTuple<GreaterThanOrEqual<T1, 0> extends true ? T1 : number, VariablePartOfArray<T>[number]>
|
|
1615
|
+
: [],
|
|
1566
1616
|
> =
|
|
1567
1617
|
SplitIndex extends 0
|
|
1568
1618
|
? [[], T]
|
|
@@ -1674,173 +1724,58 @@ type LiteralUnion<
|
|
|
1674
1724
|
> = LiteralType | (BaseType & Record<never, never>);
|
|
1675
1725
|
|
|
1676
1726
|
/**
|
|
1677
|
-
|
|
1727
|
+
Returns the last element of a union type.
|
|
1678
1728
|
|
|
1679
|
-
@
|
|
1729
|
+
@example
|
|
1730
|
+
```
|
|
1731
|
+
type Last = LastOfUnion<1 | 2 | 3>;
|
|
1732
|
+
//=> 3
|
|
1733
|
+
```
|
|
1680
1734
|
*/
|
|
1681
|
-
type
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
@default false
|
|
1686
|
-
*/
|
|
1687
|
-
recurseIntoArrays?: boolean;
|
|
1688
|
-
};
|
|
1735
|
+
type LastOfUnion<T> =
|
|
1736
|
+
UnionToIntersection<T extends any ? () => T : never> extends () => (infer R)
|
|
1737
|
+
? R
|
|
1738
|
+
: never;
|
|
1689
1739
|
|
|
1690
1740
|
/**
|
|
1691
|
-
|
|
1741
|
+
Convert a union type into an unordered tuple type of its elements.
|
|
1692
1742
|
|
|
1693
|
-
|
|
1743
|
+
"Unordered" means the elements of the tuple are not guaranteed to be in the same order as in the union type. The arrangement can appear random and may change at any time.
|
|
1694
1744
|
|
|
1695
|
-
|
|
1696
|
-
- You want a safe object type where each key exists in the union object.
|
|
1697
|
-
- You want to focus on the common fields of the union type and don't want to have to care about the other fields.
|
|
1745
|
+
This can be useful when you have objects with a finite set of keys and want a type defining only the allowed keys, but do not want to repeat yourself.
|
|
1698
1746
|
|
|
1699
1747
|
@example
|
|
1700
1748
|
```
|
|
1701
|
-
import type {
|
|
1702
|
-
|
|
1703
|
-
type Cat = {
|
|
1704
|
-
info: {
|
|
1705
|
-
name: string;
|
|
1706
|
-
type: 'cat';
|
|
1707
|
-
catType: string;
|
|
1708
|
-
};
|
|
1709
|
-
};
|
|
1710
|
-
|
|
1711
|
-
type Dog = {
|
|
1712
|
-
info: {
|
|
1713
|
-
name: string;
|
|
1714
|
-
type: 'dog';
|
|
1715
|
-
dogType: string;
|
|
1716
|
-
};
|
|
1717
|
-
};
|
|
1718
|
-
|
|
1719
|
-
function displayPetInfo(petInfo: (Cat | Dog)['info']) {
|
|
1720
|
-
// typeof petInfo =>
|
|
1721
|
-
// {
|
|
1722
|
-
// name: string;
|
|
1723
|
-
// type: 'cat';
|
|
1724
|
-
// catType: string; // Needn't care about this field, because it's not a common pet info field.
|
|
1725
|
-
// } | {
|
|
1726
|
-
// name: string;
|
|
1727
|
-
// type: 'dog';
|
|
1728
|
-
// dogType: string; // Needn't care about this field, because it's not a common pet info field.
|
|
1729
|
-
// }
|
|
1730
|
-
|
|
1731
|
-
// petInfo type is complex and have some needless fields
|
|
1732
|
-
|
|
1733
|
-
console.log('name: ', petInfo.name);
|
|
1734
|
-
console.log('type: ', petInfo.type);
|
|
1735
|
-
}
|
|
1736
|
-
|
|
1737
|
-
function displayPetInfo(petInfo: SharedUnionFieldsDeep<Cat | Dog>['info']) {
|
|
1738
|
-
// typeof petInfo =>
|
|
1739
|
-
// {
|
|
1740
|
-
// name: string;
|
|
1741
|
-
// type: 'cat' | 'dog';
|
|
1742
|
-
// }
|
|
1749
|
+
import type {UnionToTuple} from 'type-fest';
|
|
1743
1750
|
|
|
1744
|
-
|
|
1751
|
+
type Numbers = 1 | 2 | 3;
|
|
1752
|
+
type NumbersTuple = UnionToTuple<Numbers>;
|
|
1753
|
+
//=> [1, 2, 3]
|
|
1754
|
+
```
|
|
1745
1755
|
|
|
1746
|
-
|
|
1747
|
-
console.log('type: ', petInfo.type);
|
|
1748
|
-
}
|
|
1756
|
+
@example
|
|
1749
1757
|
```
|
|
1758
|
+
import type {UnionToTuple} from 'type-fest';
|
|
1750
1759
|
|
|
1751
|
-
|
|
1760
|
+
const pets = {
|
|
1761
|
+
dog: '🐶',
|
|
1762
|
+
cat: '🐱',
|
|
1763
|
+
snake: '🐍',
|
|
1764
|
+
};
|
|
1752
1765
|
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
*/
|
|
1756
|
-
type SharedUnionFieldsDeep<Union, Options extends SharedUnionFieldsDeepOptions = {recurseIntoArrays: false}> =
|
|
1757
|
-
// `Union extends` will convert `Union`
|
|
1758
|
-
// to a [distributive conditionaltype](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
|
|
1759
|
-
// But this is not what we want, so we need to wrap `Union` with `[]` to prevent it.
|
|
1760
|
-
[Union] extends [NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>]
|
|
1761
|
-
? Union
|
|
1762
|
-
: [Union] extends [UnknownArray]
|
|
1763
|
-
? Options['recurseIntoArrays'] extends true
|
|
1764
|
-
? SetArrayAccess<SharedArrayUnionFieldsDeep<Union, Options>, IsArrayReadonly<Union>>
|
|
1765
|
-
: Union
|
|
1766
|
-
: [Union] extends [object]
|
|
1767
|
-
? SharedObjectUnionFieldsDeep<Union, Options>
|
|
1768
|
-
: Union;
|
|
1769
|
-
|
|
1770
|
-
/**
|
|
1771
|
-
Same as `SharedUnionFieldsDeep`, but accepts only `object`s and as inputs. Internal helper for `SharedUnionFieldsDeep`.
|
|
1772
|
-
*/
|
|
1773
|
-
type SharedObjectUnionFieldsDeep<Union, Options extends SharedUnionFieldsDeepOptions> =
|
|
1774
|
-
// `keyof Union` can extract the same key in union type, if there is no same key, return never.
|
|
1775
|
-
keyof Union extends infer Keys
|
|
1776
|
-
? IsNever<Keys> extends false
|
|
1777
|
-
? {
|
|
1778
|
-
[Key in keyof Union]:
|
|
1779
|
-
Union[Key] extends NonRecursiveType
|
|
1780
|
-
? Union[Key]
|
|
1781
|
-
// Remove `undefined` from the union to support optional
|
|
1782
|
-
// fields, then recover `undefined` if union was already undefined.
|
|
1783
|
-
: SharedUnionFieldsDeep<Exclude<Union[Key], undefined>, Options> | (
|
|
1784
|
-
undefined extends Required<Union>[Key] ? undefined : never
|
|
1785
|
-
)
|
|
1786
|
-
}
|
|
1787
|
-
: {}
|
|
1788
|
-
: Union;
|
|
1766
|
+
type Pet = keyof typeof pets;
|
|
1767
|
+
//=> 'dog' | 'cat' | 'snake'
|
|
1789
1768
|
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
type SharedArrayUnionFieldsDeep<Union extends UnknownArray, Options extends SharedUnionFieldsDeepOptions> =
|
|
1794
|
-
// Restore the readonly modifier of the array.
|
|
1795
|
-
SetArrayAccess<
|
|
1796
|
-
InternalSharedArrayUnionFieldsDeep<Union, Options>,
|
|
1797
|
-
IsArrayReadonly<Union>
|
|
1798
|
-
>;
|
|
1769
|
+
const petList = Object.keys(pets) as UnionToTuple<Pet>;
|
|
1770
|
+
//=> ['dog', 'cat', 'snake']
|
|
1771
|
+
```
|
|
1799
1772
|
|
|
1800
|
-
|
|
1801
|
-
Internal helper for `SharedArrayUnionFieldsDeep`. Needn't care the `readonly` modifier of arrays.
|
|
1773
|
+
@category Array
|
|
1802
1774
|
*/
|
|
1803
|
-
type
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
> =
|
|
1808
|
-
// We should build a minimum possible length tuple where each element in the tuple exists in the union tuple.
|
|
1809
|
-
IsNever<TupleLength<Union>> extends true
|
|
1810
|
-
// Rule 1: If all the arrays in the union have non-fixed lengths,
|
|
1811
|
-
// like `Array<string> | [number, ...string[]]`
|
|
1812
|
-
// we should build a tuple that is [the_fixed_parts_of_union, ...the_rest_of_union[]].
|
|
1813
|
-
// For example: `InternalSharedArrayUnionFieldsDeep<Array<string> | [number, ...string[]]>`
|
|
1814
|
-
// => `[string | number, ...string[]]`.
|
|
1815
|
-
? ResultTuple['length'] extends UnionMax<StaticPartOfArray<Union>['length']>
|
|
1816
|
-
? [
|
|
1817
|
-
// The fixed-length part of the tuple.
|
|
1818
|
-
...ResultTuple,
|
|
1819
|
-
// The rest of the union.
|
|
1820
|
-
// Due to `ResultTuple` is the maximum possible fixed-length part of the tuple,
|
|
1821
|
-
// so we can use `StaticPartOfArray` to get the rest of the union.
|
|
1822
|
-
...Array<
|
|
1823
|
-
SharedUnionFieldsDeep<VariablePartOfArray<Union>[number], Options>
|
|
1824
|
-
>,
|
|
1825
|
-
]
|
|
1826
|
-
// Build the fixed-length tuple recursively.
|
|
1827
|
-
: InternalSharedArrayUnionFieldsDeep<
|
|
1828
|
-
Union, Options,
|
|
1829
|
-
[...ResultTuple, SharedUnionFieldsDeep<Union[ResultTuple['length']], Options>]
|
|
1830
|
-
>
|
|
1831
|
-
// Rule 2: If at least one of the arrays in the union have fixed lengths,
|
|
1832
|
-
// like `Array<string> | [number, string]`,
|
|
1833
|
-
// we should build a tuple of the smallest possible length to ensure any
|
|
1834
|
-
// item in the result tuple exists in the union tuple.
|
|
1835
|
-
// For example: `InternalSharedArrayUnionFieldsDeep<Array<string> | [number, string]>`
|
|
1836
|
-
// => `[string | number, string]`.
|
|
1837
|
-
: ResultTuple['length'] extends UnionMin<TupleLength<Union>>
|
|
1838
|
-
? ResultTuple
|
|
1839
|
-
// As above, build tuple recursively.
|
|
1840
|
-
: InternalSharedArrayUnionFieldsDeep<
|
|
1841
|
-
Union, Options,
|
|
1842
|
-
[...ResultTuple, SharedUnionFieldsDeep<Union[ResultTuple['length']], Options>]
|
|
1843
|
-
>;
|
|
1775
|
+
type UnionToTuple<T, L = LastOfUnion<T>> =
|
|
1776
|
+
IsNever<T> extends false
|
|
1777
|
+
? [...UnionToTuple<Exclude<T, L>>, L]
|
|
1778
|
+
: [];
|
|
1844
1779
|
|
|
1845
1780
|
/**
|
|
1846
1781
|
Omit properties from a deeply-nested object.
|
|
@@ -1926,11 +1861,19 @@ type AddressInfo = OmitDeep<Info1, 'address.1.foo'>;
|
|
|
1926
1861
|
*/
|
|
1927
1862
|
type OmitDeep<T, PathUnion extends LiteralUnion<Paths<T>, string>> =
|
|
1928
1863
|
SimplifyDeep<
|
|
1929
|
-
|
|
1930
|
-
{[P in PathUnion]: OmitDeepWithOnePath<T, P>}[PathUnion]
|
|
1931
|
-
>,
|
|
1864
|
+
OmitDeepHelper<T, UnionToTuple<PathUnion>>,
|
|
1932
1865
|
UnknownArray>;
|
|
1933
1866
|
|
|
1867
|
+
/**
|
|
1868
|
+
Internal helper for {@link OmitDeep}.
|
|
1869
|
+
|
|
1870
|
+
Recursively transforms `T` by applying {@link OmitDeepWithOnePath} for each path in `PathTuple`.
|
|
1871
|
+
*/
|
|
1872
|
+
type OmitDeepHelper<T, PathTuple extends UnknownArray> =
|
|
1873
|
+
PathTuple extends [infer Path, ...infer RestPaths]
|
|
1874
|
+
? OmitDeepHelper<OmitDeepWithOnePath<T, Path & (string | number)>, RestPaths>
|
|
1875
|
+
: T;
|
|
1876
|
+
|
|
1934
1877
|
/**
|
|
1935
1878
|
Omit one path from the given object/array.
|
|
1936
1879
|
*/
|
|
@@ -2018,6 +1961,41 @@ type StringKeysOfFoo = StringKeyOf<Foo>;
|
|
|
2018
1961
|
*/
|
|
2019
1962
|
type StringKeyOf<BaseType> = `${Extract<keyof BaseType, string | number>}`;
|
|
2020
1963
|
|
|
1964
|
+
/**
|
|
1965
|
+
Split options.
|
|
1966
|
+
|
|
1967
|
+
@see {@link Split}
|
|
1968
|
+
*/
|
|
1969
|
+
type SplitOptions = {
|
|
1970
|
+
/**
|
|
1971
|
+
When enabled, instantiations with non-literal string types (e.g., `string`, `Uppercase<string>`, `on${string}`) simply return back `string[]` without performing any splitting, as the exact structure cannot be statically determined.
|
|
1972
|
+
|
|
1973
|
+
Note: In the future, this option might be enabled by default, so if you currently rely on this being disabled, you should consider explicitly enabling it.
|
|
1974
|
+
|
|
1975
|
+
@default false
|
|
1976
|
+
|
|
1977
|
+
@example
|
|
1978
|
+
```ts
|
|
1979
|
+
type Example1 = Split<`foo.${string}.bar`, '.', {strictLiteralChecks: false}>;
|
|
1980
|
+
//=> ['foo', string, 'bar']
|
|
1981
|
+
|
|
1982
|
+
type Example2 = Split<`foo.${string}`, '.', {strictLiteralChecks: true}>;
|
|
1983
|
+
//=> string[]
|
|
1984
|
+
|
|
1985
|
+
type Example3 = Split<'foobarbaz', `b${string}`, {strictLiteralChecks: false}>;
|
|
1986
|
+
//=> ['foo', 'r', 'z']
|
|
1987
|
+
|
|
1988
|
+
type Example4 = Split<'foobarbaz', `b${string}`, {strictLiteralChecks: true}>;
|
|
1989
|
+
//=> string[]
|
|
1990
|
+
```
|
|
1991
|
+
*/
|
|
1992
|
+
strictLiteralChecks?: boolean;
|
|
1993
|
+
};
|
|
1994
|
+
|
|
1995
|
+
type DefaultSplitOptions = {
|
|
1996
|
+
strictLiteralChecks: false;
|
|
1997
|
+
};
|
|
1998
|
+
|
|
2021
1999
|
/**
|
|
2022
2000
|
Represents an array of strings split using a given character or character set.
|
|
2023
2001
|
|
|
@@ -2036,23 +2014,37 @@ let array: Item[];
|
|
|
2036
2014
|
array = split(items, ',');
|
|
2037
2015
|
```
|
|
2038
2016
|
|
|
2017
|
+
@see {@link SplitOptions}
|
|
2018
|
+
|
|
2039
2019
|
@category String
|
|
2040
2020
|
@category Template literal
|
|
2041
2021
|
*/
|
|
2042
2022
|
type Split<
|
|
2043
2023
|
S extends string,
|
|
2044
2024
|
Delimiter extends string,
|
|
2045
|
-
|
|
2025
|
+
Options extends SplitOptions = {},
|
|
2026
|
+
> = SplitHelper<S, Delimiter, {
|
|
2027
|
+
strictLiteralChecks: Options['strictLiteralChecks'] extends boolean ? Options['strictLiteralChecks'] : DefaultSplitOptions['strictLiteralChecks'];
|
|
2028
|
+
}>;
|
|
2046
2029
|
|
|
2047
2030
|
type SplitHelper<
|
|
2048
2031
|
S extends string,
|
|
2049
2032
|
Delimiter extends string,
|
|
2033
|
+
Options extends Required<SplitOptions>,
|
|
2050
2034
|
Accumulator extends string[] = [],
|
|
2051
|
-
> = S extends
|
|
2052
|
-
?
|
|
2053
|
-
|
|
2054
|
-
?
|
|
2055
|
-
|
|
2035
|
+
> = S extends string // For distributing `S`
|
|
2036
|
+
? Delimiter extends string // For distributing `Delimeter`
|
|
2037
|
+
// If `strictLiteralChecks` is `false` OR `S` and `Delimiter` both are string literals, then perform the split
|
|
2038
|
+
? Or<Not<Options['strictLiteralChecks']>, And<IsStringLiteral<S>, IsStringLiteral<Delimiter>>> extends true
|
|
2039
|
+
? S extends `${infer Head}${Delimiter}${infer Tail}`
|
|
2040
|
+
? SplitHelper<Tail, Delimiter, Options, [...Accumulator, Head]>
|
|
2041
|
+
: Delimiter extends ''
|
|
2042
|
+
? Accumulator
|
|
2043
|
+
: [...Accumulator, S]
|
|
2044
|
+
// Otherwise, return `string[]`
|
|
2045
|
+
: string[]
|
|
2046
|
+
: never // Should never happen
|
|
2047
|
+
: never; // Should never happen
|
|
2056
2048
|
|
|
2057
2049
|
type GetOptions = {
|
|
2058
2050
|
/**
|