type-fest 4.23.0 → 4.25.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/index.d.ts +2 -0
- package/package.json +1 -1
- package/readme.md +2 -0
- package/source/arrayable.d.ts +26 -0
- package/source/internal/numeric.d.ts +27 -0
- package/source/merge-deep.d.ts +1 -1
- package/source/omit-deep.d.ts +19 -0
- package/source/paths.d.ts +84 -15
- package/source/string-repeat.d.ts +43 -0
package/index.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ export type {UndefinedOnPartialDeep} from './source/undefined-on-partial-deep';
|
|
|
36
36
|
export type {ReadonlyDeep} from './source/readonly-deep';
|
|
37
37
|
export type {LiteralUnion} from './source/literal-union';
|
|
38
38
|
export type {Promisable} from './source/promisable';
|
|
39
|
+
export type {Arrayable} from './source/arrayable';
|
|
39
40
|
export type {Opaque, UnwrapOpaque, Tagged, GetTagMetadata, UnwrapTagged} from './source/opaque';
|
|
40
41
|
export type {InvariantOf} from './source/invariant-of';
|
|
41
42
|
export type {SetOptional} from './source/set-optional';
|
|
@@ -154,6 +155,7 @@ export type {Join} from './source/join';
|
|
|
154
155
|
export type {Split} from './source/split';
|
|
155
156
|
export type {Trim} from './source/trim';
|
|
156
157
|
export type {Replace} from './source/replace';
|
|
158
|
+
export type {StringRepeat} from './source/string-repeat';
|
|
157
159
|
export type {Includes} from './source/includes';
|
|
158
160
|
export type {Get} from './source/get';
|
|
159
161
|
export type {LastArrayElement} from './source/last-array-element';
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -269,9 +269,11 @@ type ShouldBeNever = IfAny<'not any', 'not never', 'never'>;
|
|
|
269
269
|
- [`Split`](source/split.d.ts) - Represents an array of strings split using a given character or character set.
|
|
270
270
|
- [`Replace`](source/replace.d.ts) - Represents a string with some or all matches replaced by a replacement.
|
|
271
271
|
- [`StringSlice`](source/string-slice.d.ts) - Returns a string slice of a given range, just like `String#slice()`.
|
|
272
|
+
- [`StringRepeat`](source/string-repeat.d.ts) - Returns a new string which contains the specified number of copies of a given string, just like `String#repeat()`.
|
|
272
273
|
|
|
273
274
|
### Array
|
|
274
275
|
|
|
276
|
+
- [`Arrayable`](source/arrayable.d.ts) - Create a type that represents either the value or an array of the value.
|
|
275
277
|
- [`Includes`](source/includes.d.ts) - Returns a boolean for whether the given array includes the given item.
|
|
276
278
|
- [`Join`](source/join.d.ts) - Join an array of strings and/or numbers using the given string as a delimiter.
|
|
277
279
|
- [`ArraySlice`](source/array-slice.d.ts) - Returns an array slice of a given range, just like `Array#slice()`.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Create a type that represents either the value or an array of the value.
|
|
3
|
+
|
|
4
|
+
@see Promisable
|
|
5
|
+
|
|
6
|
+
@example
|
|
7
|
+
```
|
|
8
|
+
import type {Arrayable} from 'type-fest';
|
|
9
|
+
|
|
10
|
+
function bundle(input: string, output: Arrayable<string>) {
|
|
11
|
+
const outputList = Array.isArray(output) ? output : [output];
|
|
12
|
+
|
|
13
|
+
// …
|
|
14
|
+
|
|
15
|
+
for (const output of outputList) {
|
|
16
|
+
console.log(`write to: ${output}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
bundle('src/index.js', 'dist/index.js');
|
|
21
|
+
bundle('src/index.js', ['dist/index.cjs', 'dist/index.mjs']);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
@category Array
|
|
25
|
+
*/
|
|
26
|
+
export type Arrayable<T> = T | readonly T[];
|
|
@@ -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/omit-deep.d.ts
CHANGED
|
@@ -37,6 +37,25 @@ type UsefulInfo = OmitDeep<Info, 'userInfo.uselessInfo'>;
|
|
|
37
37
|
// userInfo: {
|
|
38
38
|
// name: string;
|
|
39
39
|
// };
|
|
40
|
+
// };
|
|
41
|
+
|
|
42
|
+
// Supports removing multiple paths
|
|
43
|
+
type Info1 = {
|
|
44
|
+
userInfo: {
|
|
45
|
+
name: string;
|
|
46
|
+
uselessField: string;
|
|
47
|
+
uselessInfo: {
|
|
48
|
+
foo: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
type UsefulInfo1 = OmitDeep<Info1, 'userInfo.uselessInfo' | 'userInfo.uselessField'>;
|
|
54
|
+
// type UsefulInfo1 = {
|
|
55
|
+
// userInfo: {
|
|
56
|
+
// name: string;
|
|
57
|
+
// };
|
|
58
|
+
// };
|
|
40
59
|
|
|
41
60
|
// Supports array
|
|
42
61
|
type A = OmitDeep<[1, 'foo', 2], 1>;
|
package/source/paths.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
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
5
|
import type {Subtract} from './subtract';
|
|
7
6
|
import type {GreaterThan} from './greater-than';
|
|
@@ -18,6 +17,44 @@ export type PathsOptions = {
|
|
|
18
17
|
@default 10
|
|
19
18
|
*/
|
|
20
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;
|
|
21
58
|
};
|
|
22
59
|
|
|
23
60
|
/**
|
|
@@ -61,7 +98,14 @@ open('listB.1'); // TypeError. Because listB only has one element.
|
|
|
61
98
|
@category Object
|
|
62
99
|
@category Array
|
|
63
100
|
*/
|
|
64
|
-
export type Paths<T, Options extends PathsOptions = {}> =
|
|
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
|
+
}>;
|
|
107
|
+
|
|
108
|
+
type _Paths<T, Options extends Required<PathsOptions>> =
|
|
65
109
|
T extends NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
|
|
66
110
|
? never
|
|
67
111
|
: IsAny<T> extends true
|
|
@@ -76,25 +120,50 @@ export type Paths<T, Options extends PathsOptions = {}> =
|
|
|
76
120
|
? InternalPaths<T, Options>
|
|
77
121
|
: never;
|
|
78
122
|
|
|
79
|
-
type InternalPaths<T, Options extends PathsOptions =
|
|
80
|
-
|
|
123
|
+
type InternalPaths<T, Options extends Required<PathsOptions>> =
|
|
124
|
+
Options['maxRecursionDepth'] extends infer MaxDepth extends number
|
|
81
125
|
? Required<T> extends infer T
|
|
82
126
|
? T extends EmptyObject | readonly []
|
|
83
127
|
? never
|
|
84
128
|
: {
|
|
85
129
|
[Key in keyof T]:
|
|
86
130
|
Key extends string | number // Limit `Key` to string or number.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
GreaterThan<MaxDepth, 0> extends true // Limit the depth to prevent infinite recursion
|
|
93
|
-
? IsNever<Paths<T[Key], {maxRecursionDepth: Subtract<MaxDepth, 1>}>> extends false
|
|
94
|
-
? `${Key}.${Paths<T[Key], {maxRecursionDepth: Subtract<MaxDepth, 1>}>}`
|
|
95
|
-
: never
|
|
131
|
+
? (
|
|
132
|
+
Options['bracketNotation'] extends true
|
|
133
|
+
? IsNumberLike<Key> extends true
|
|
134
|
+
? `[${Key}]`
|
|
135
|
+
: (Key | ToString<Key>)
|
|
96
136
|
: never
|
|
97
|
-
|
|
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
|
+
)
|
|
166
|
+
: never
|
|
98
167
|
: never
|
|
99
168
|
}[keyof T & (T extends UnknownArray ? number : unknown)]
|
|
100
169
|
: never
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type {IsNegative} from './numeric';
|
|
2
|
+
import type {Subtract} from './subtract';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
Returns a new string which contains the specified number of copies of a given string, just like `String#repeat()`.
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
```
|
|
9
|
+
import {StringRepeat} from 'type-fest';
|
|
10
|
+
|
|
11
|
+
declare function stringRepeat<
|
|
12
|
+
Input extends string,
|
|
13
|
+
Count extends number
|
|
14
|
+
>(input: Input, count: Count): StringRepeat<Input, Count>;
|
|
15
|
+
|
|
16
|
+
// The return type is the exact string literal, not just `string`.
|
|
17
|
+
|
|
18
|
+
stringRepeat('foo', 2);
|
|
19
|
+
//=> 'foofoo'
|
|
20
|
+
|
|
21
|
+
stringRepeat('=', 3);
|
|
22
|
+
//=> '==='
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
@category String
|
|
26
|
+
@category Template literal
|
|
27
|
+
*/
|
|
28
|
+
export type StringRepeat<
|
|
29
|
+
Input extends string,
|
|
30
|
+
Count extends number,
|
|
31
|
+
> = number extends Count
|
|
32
|
+
? Input extends ''
|
|
33
|
+
? ''
|
|
34
|
+
: string
|
|
35
|
+
: IsNegative<Count> extends true
|
|
36
|
+
? never
|
|
37
|
+
: Count extends 0
|
|
38
|
+
? ''
|
|
39
|
+
: string extends Input
|
|
40
|
+
? string
|
|
41
|
+
: StringRepeat<Input, Subtract<Count, 1>> extends infer R extends string
|
|
42
|
+
? `${Input}${R}`
|
|
43
|
+
: never;
|