type-fest 4.22.1 → 4.24.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/package.json +1 -1
- package/source/internal/numeric.d.ts +27 -0
- package/source/merge-deep.d.ts +1 -1
- package/source/paths.d.ts +112 -27
package/package.json
CHANGED
|
@@ -19,6 +19,33 @@ NumberAbsolute<NegativeInfinity>
|
|
|
19
19
|
*/
|
|
20
20
|
export type NumberAbsolute<N extends number> = `${N}` extends `-${infer StringPositiveN}` ? StringToNumber<StringPositiveN> : N;
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
Check whether the given type is a number or a number string.
|
|
24
|
+
|
|
25
|
+
Supports floating-point as a string.
|
|
26
|
+
|
|
27
|
+
@example
|
|
28
|
+
```
|
|
29
|
+
type A = IsNumberLike<'1'>;
|
|
30
|
+
//=> true
|
|
31
|
+
|
|
32
|
+
type B = IsNumberLike<'-1.1'>;
|
|
33
|
+
//=> true
|
|
34
|
+
|
|
35
|
+
type C = IsNumberLike<1>;
|
|
36
|
+
//=> true
|
|
37
|
+
|
|
38
|
+
type D = IsNumberLike<'a'>;
|
|
39
|
+
//=> false
|
|
40
|
+
*/
|
|
41
|
+
export type IsNumberLike<N> =
|
|
42
|
+
N extends number ? true
|
|
43
|
+
: N extends `${number}`
|
|
44
|
+
? true
|
|
45
|
+
: N extends `${number}.${number}`
|
|
46
|
+
? true
|
|
47
|
+
: false;
|
|
48
|
+
|
|
22
49
|
/**
|
|
23
50
|
Returns the minimum number in the given union of numbers.
|
|
24
51
|
|
package/source/merge-deep.d.ts
CHANGED
package/source/paths.d.ts
CHANGED
|
@@ -1,10 +1,61 @@
|
|
|
1
|
-
import type {StaticPartOfArray, VariablePartOfArray, NonRecursiveType, ToString} from './internal';
|
|
1
|
+
import type {StaticPartOfArray, VariablePartOfArray, NonRecursiveType, ToString, IsNumberLike} from './internal';
|
|
2
2
|
import type {EmptyObject} from './empty-object';
|
|
3
3
|
import type {IsAny} from './is-any';
|
|
4
|
-
import type {IsNever} from './is-never';
|
|
5
4
|
import type {UnknownArray} from './unknown-array';
|
|
6
|
-
import type {
|
|
7
|
-
import type {
|
|
5
|
+
import type {Subtract} from './subtract';
|
|
6
|
+
import type {GreaterThan} from './greater-than';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
Paths options.
|
|
10
|
+
|
|
11
|
+
@see {@link Paths}
|
|
12
|
+
*/
|
|
13
|
+
export type PathsOptions = {
|
|
14
|
+
/**
|
|
15
|
+
The maximum depth to recurse when searching for paths.
|
|
16
|
+
|
|
17
|
+
@default 10
|
|
18
|
+
*/
|
|
19
|
+
maxRecursionDepth?: number;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
Use bracket notation for array indices and numeric object keys.
|
|
23
|
+
|
|
24
|
+
@default false
|
|
25
|
+
|
|
26
|
+
@example
|
|
27
|
+
```
|
|
28
|
+
type ArrayExample = {
|
|
29
|
+
array: ['foo'];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
type A = Paths<ArrayExample, {bracketNotation: false}>;
|
|
33
|
+
//=> 'array' | 'array.0'
|
|
34
|
+
|
|
35
|
+
type B = Paths<ArrayExample, {bracketNotation: true}>;
|
|
36
|
+
//=> 'array' | 'array[0]'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
@example
|
|
40
|
+
```
|
|
41
|
+
type NumberKeyExample = {
|
|
42
|
+
1: ['foo'];
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
type A = Paths<NumberKeyExample, {bracketNotation: false}>;
|
|
46
|
+
//=> 1 | '1' | '1.0'
|
|
47
|
+
|
|
48
|
+
type B = Paths<NumberKeyExample, {bracketNotation: true}>;
|
|
49
|
+
//=> '[1]' | '[1][0]'
|
|
50
|
+
```
|
|
51
|
+
*/
|
|
52
|
+
bracketNotation?: boolean;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
type DefaultPathsOptions = {
|
|
56
|
+
maxRecursionDepth: 10;
|
|
57
|
+
bracketNotation: false;
|
|
58
|
+
};
|
|
8
59
|
|
|
9
60
|
/**
|
|
10
61
|
Generate a union of all possible paths to properties in the given object.
|
|
@@ -47,9 +98,14 @@ open('listB.1'); // TypeError. Because listB only has one element.
|
|
|
47
98
|
@category Object
|
|
48
99
|
@category Array
|
|
49
100
|
*/
|
|
50
|
-
export type Paths<T> =
|
|
101
|
+
export type Paths<T, Options extends PathsOptions = {}> = _Paths<T, {
|
|
102
|
+
// Set default maxRecursionDepth to 10
|
|
103
|
+
maxRecursionDepth: Options['maxRecursionDepth'] extends number ? Options['maxRecursionDepth'] : DefaultPathsOptions['maxRecursionDepth'];
|
|
104
|
+
// Set default bracketNotation to false
|
|
105
|
+
bracketNotation: Options['bracketNotation'] extends boolean ? Options['bracketNotation'] : DefaultPathsOptions['bracketNotation'];
|
|
106
|
+
}>;
|
|
51
107
|
|
|
52
|
-
type
|
|
108
|
+
type _Paths<T, Options extends Required<PathsOptions>> =
|
|
53
109
|
T extends NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
|
|
54
110
|
? never
|
|
55
111
|
: IsAny<T> extends true
|
|
@@ -57,29 +113,58 @@ type Paths_<T, Depth extends number = 0> =
|
|
|
57
113
|
: T extends UnknownArray
|
|
58
114
|
? number extends T['length']
|
|
59
115
|
// We need to handle the fixed and non-fixed index part of the array separately.
|
|
60
|
-
? InternalPaths<StaticPartOfArray<T>,
|
|
61
|
-
| InternalPaths<Array<VariablePartOfArray<T>[number]>,
|
|
62
|
-
: InternalPaths<T,
|
|
116
|
+
? InternalPaths<StaticPartOfArray<T>, Options>
|
|
117
|
+
| InternalPaths<Array<VariablePartOfArray<T>[number]>, Options>
|
|
118
|
+
: InternalPaths<T, Options>
|
|
63
119
|
: T extends object
|
|
64
|
-
? InternalPaths<T,
|
|
120
|
+
? InternalPaths<T, Options>
|
|
65
121
|
: never;
|
|
66
122
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
?
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
123
|
+
type InternalPaths<T, Options extends Required<PathsOptions>> =
|
|
124
|
+
Options['maxRecursionDepth'] extends infer MaxDepth extends number
|
|
125
|
+
? Required<T> extends infer T
|
|
126
|
+
? T extends EmptyObject | readonly []
|
|
127
|
+
? never
|
|
128
|
+
: {
|
|
129
|
+
[Key in keyof T]:
|
|
130
|
+
Key extends string | number // Limit `Key` to string or number.
|
|
131
|
+
? (
|
|
132
|
+
Options['bracketNotation'] extends true
|
|
133
|
+
? IsNumberLike<Key> extends true
|
|
134
|
+
? `[${Key}]`
|
|
135
|
+
: (Key | ToString<Key>)
|
|
136
|
+
: never
|
|
137
|
+
|
|
|
138
|
+
Options['bracketNotation'] extends false
|
|
139
|
+
// If `Key` is a number, return `Key | `${Key}``, because both `array[0]` and `array['0']` work.
|
|
140
|
+
? (Key | ToString<Key>)
|
|
141
|
+
: never
|
|
142
|
+
) extends infer TranformedKey extends string | number ?
|
|
143
|
+
// 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
|
|
144
|
+
// 2. If style is 'a.0.b', transform 'Key' to `${Key}` | Key
|
|
145
|
+
| TranformedKey
|
|
146
|
+
| (
|
|
147
|
+
// Recursively generate paths for the current key
|
|
148
|
+
GreaterThan<MaxDepth, 0> extends true // Limit the depth to prevent infinite recursion
|
|
149
|
+
? _Paths<T[Key], {bracketNotation: Options['bracketNotation']; maxRecursionDepth: Subtract<MaxDepth, 1>}> extends infer SubPath
|
|
150
|
+
? SubPath extends string | number
|
|
151
|
+
? (
|
|
152
|
+
Options['bracketNotation'] extends true
|
|
153
|
+
? SubPath extends `[${any}]` | `[${any}]${string}`
|
|
154
|
+
? `${TranformedKey}${SubPath}` // If next node is number key like `[3]`, no need to add `.` before it.
|
|
155
|
+
: `${TranformedKey}.${SubPath}`
|
|
156
|
+
: never
|
|
157
|
+
) | (
|
|
158
|
+
Options['bracketNotation'] extends false
|
|
159
|
+
? `${TranformedKey}.${SubPath}`
|
|
160
|
+
: never
|
|
161
|
+
)
|
|
162
|
+
: never
|
|
163
|
+
: never
|
|
164
|
+
: never
|
|
165
|
+
)
|
|
81
166
|
: never
|
|
82
167
|
: never
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
|
|
168
|
+
}[keyof T & (T extends UnknownArray ? number : unknown)]
|
|
169
|
+
: never
|
|
170
|
+
: never;
|