type-fest 3.7.2 → 3.9.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 +8 -0
- package/package.json +1 -1
- package/readme.md +34 -1
- package/source/if-any.d.ts +24 -0
- package/source/if-never.d.ts +24 -0
- package/source/if-unknown.d.ts +24 -0
- package/source/internal.d.ts +6 -17
- package/source/is-any.d.ts +29 -0
- package/source/is-equal.d.ts +1 -0
- package/source/is-literal.d.ts +7 -6
- package/source/is-never.d.ts +49 -0
- package/source/is-unknown.d.ts +52 -0
- package/source/join.d.ts +42 -9
- package/source/jsonify.d.ts +2 -1
- package/source/literal-to-primitive-deep.d.ts +36 -0
- package/source/override-properties.d.ts +26 -0
- package/source/set-return-type.d.ts +1 -1
package/index.d.ts
CHANGED
|
@@ -55,6 +55,7 @@ export type {Jsonify} from './source/jsonify';
|
|
|
55
55
|
export type {Jsonifiable} from './source/jsonifiable';
|
|
56
56
|
export type {Schema} from './source/schema';
|
|
57
57
|
export type {LiteralToPrimitive} from './source/literal-to-primitive';
|
|
58
|
+
export type {LiteralToPrimitiveDeep} from './source/literal-to-primitive-deep';
|
|
58
59
|
export type {
|
|
59
60
|
PositiveInfinity,
|
|
60
61
|
NegativeInfinity,
|
|
@@ -71,6 +72,7 @@ export type {StringKeyOf} from './source/string-key-of';
|
|
|
71
72
|
export type {Exact} from './source/exact';
|
|
72
73
|
export type {ReadonlyTuple} from './source/readonly-tuple';
|
|
73
74
|
export type {OptionalKeysOf} from './source/optional-keys-of';
|
|
75
|
+
export type {OverrideProperties} from './source/override-properties';
|
|
74
76
|
export type {HasOptionalKeys} from './source/has-optional-keys';
|
|
75
77
|
export type {RequiredKeysOf} from './source/required-keys-of';
|
|
76
78
|
export type {HasRequiredKeys} from './source/has-required-keys';
|
|
@@ -84,6 +86,12 @@ export type {
|
|
|
84
86
|
IsBooleanLiteral,
|
|
85
87
|
IsSymbolLiteral,
|
|
86
88
|
} from './source/is-literal';
|
|
89
|
+
export type {IsAny} from './source/is-any';
|
|
90
|
+
export type {IfAny} from './source/if-any';
|
|
91
|
+
export type {IsNever} from './source/is-never';
|
|
92
|
+
export type {IfNever} from './source/if-never';
|
|
93
|
+
export type {IsUnknown} from './source/is-unknown';
|
|
94
|
+
export type {IfUnknown} from './source/if-unknown';
|
|
87
95
|
|
|
88
96
|
// Template literal types
|
|
89
97
|
export type {CamelCase} from './source/camel-case';
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -135,6 +135,7 @@ Click the type names for complete docs.
|
|
|
135
135
|
- [`Merge`](source/merge.d.ts) - Merge two types into a new type. Keys of the second type overrides keys of the first type.
|
|
136
136
|
- [`MergeDeep`](source/merge-deep.d.ts) - Merge two objects or two arrays/tuples recursively into a new type.
|
|
137
137
|
- [`MergeExclusive`](source/merge-exclusive.d.ts) - Create a type that has mutually exclusive keys.
|
|
138
|
+
- [`OverrideProperties`](source/override-properties.d.ts) - Override only existing properties of the given type. Similar to `Merge`, but enforces that the original type has the properties you want to override.
|
|
138
139
|
- [`RequireAtLeastOne`](source/require-at-least-one.d.ts) - Create a type that requires at least one of the given keys.
|
|
139
140
|
- [`RequireExactlyOne`](source/require-exactly-one.d.ts) - Create a type that requires exactly a single key of the given keys and disallows more.
|
|
140
141
|
- [`RequireAllOrNone`](source/require-all-or-none.d.ts) - Create a type that requires all of the given keys or none of the given keys.
|
|
@@ -157,6 +158,7 @@ Click the type names for complete docs.
|
|
|
157
158
|
- [`ConditionalExcept`](source/conditional-except.d.ts) - Like `Omit` except it removes properties from a shape where the values extend the given `Condition` type.
|
|
158
159
|
- [`UnionToIntersection`](source/union-to-intersection.d.ts) - Convert a union type to an intersection type.
|
|
159
160
|
- [`LiteralToPrimitive`](source/literal-to-primitive.d.ts) - Convert a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) to the [primitive type](source/primitive.d.ts) it belongs to.
|
|
161
|
+
- [`LiteralToPrimitiveDeep`](source/literal-to-primitive-deep.d.ts) - Like `LiteralToPrimitive` except it converts literal types inside an object or array deeply.
|
|
160
162
|
- [`Stringified`](source/stringified.d.ts) - Create a type with the keys of the given type changed to `string` type.
|
|
161
163
|
- [`IterableElement`](source/iterable-element.d.ts) - Get the element type of an `Iterable`/`AsyncIterable`. For example, an array or a generator.
|
|
162
164
|
- [`Entry`](source/entry.d.ts) - Create a type that represents the type of an entry of a collection.
|
|
@@ -173,12 +175,43 @@ Click the type names for complete docs.
|
|
|
173
175
|
- [`HasRequiredKeys`](source/has-required-keys.d.ts) - Create a `true`/`false` type depending on whether the given type has any required fields.
|
|
174
176
|
- [`Spread`](source/spread.d.ts) - Mimic the type inferred by TypeScript when merging two objects or two arrays/tuples using the spread syntax.
|
|
175
177
|
- [`IsEqual`](source/is-equal.d.ts) - Returns a boolean for whether the two given types are equal.
|
|
178
|
+
- [`TaggedUnion`](source/tagged-union.d.ts) - Create a union of types that share a common discriminant property.
|
|
179
|
+
|
|
180
|
+
### Type Guard
|
|
181
|
+
|
|
182
|
+
#### `IsType` vs. `IfType`
|
|
183
|
+
|
|
184
|
+
For every `IsT` type (e.g. `IsAny`), there is an associated `IfT` type that can help simplify conditional types. While the `IsT` types return a `boolean`, the `IfT` types act like an `If`/`Else` - they resolve to the given `TypeIfT` or `TypeIfNotT` depending on whether `IsX` is `true` or not. By default, `IfT` returns a `boolean`:
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
type IfAny<T, TypeIfAny = true, TypeIfNotAny = false> = (
|
|
188
|
+
IsAny<T> extends true ? TypeIfAny : TypeIfNotAny
|
|
189
|
+
);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### Usage
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
import type {IsAny, IfAny} from 'type-fest';
|
|
196
|
+
|
|
197
|
+
type ShouldBeTrue = IsAny<any> extends true ? true : false;
|
|
198
|
+
//=> true
|
|
199
|
+
|
|
200
|
+
type ShouldBeFalse = IfAny<'not any'>;
|
|
201
|
+
//=> false
|
|
202
|
+
|
|
203
|
+
type ShouldBeNever = IfAny<'not any', 'not never', 'never'>;
|
|
204
|
+
//=> 'never'
|
|
205
|
+
```
|
|
206
|
+
|
|
176
207
|
- [`IsLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
|
|
177
208
|
- [`IsStringLiteral`](source/is-literal.d.ts) - 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).
|
|
178
209
|
- [`IsNumericLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `number` or `bigint` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
|
|
179
210
|
- [`IsBooleanLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `true` or `false` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
|
|
180
211
|
- [`IsSymbolLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `symbol` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
|
|
181
|
-
- [`
|
|
212
|
+
- [`IsAny`](source/is-any.d.ts) - Returns a boolean for whether the given type is `any`. (Conditional version: [`IfAny`](source/if-any.d.ts).)
|
|
213
|
+
- [`IsNever`](source/is-never.d.ts) - Returns a boolean for whether the given type is `never`. (Conditional version: [`IfNever`](source/if-never.d.ts).)
|
|
214
|
+
- [`IsUnknown`](source/is-unknown.d.ts) - Returns a boolean for whether the given type is `unknown`. (Conditional version: [`IfUnknown`](source/if-unknown.d.ts).)
|
|
182
215
|
|
|
183
216
|
### JSON
|
|
184
217
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type {IsAny} from './is-any';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
An if-else-like type that resolves depending on whether the given type is `any`.
|
|
5
|
+
|
|
6
|
+
@see {@link IsAny}
|
|
7
|
+
|
|
8
|
+
@example
|
|
9
|
+
```
|
|
10
|
+
import type {IfAny} from 'type-fest';
|
|
11
|
+
|
|
12
|
+
type ShouldBeTrue = IfAny<any>;
|
|
13
|
+
//=> true
|
|
14
|
+
|
|
15
|
+
type ShouldBeBar = IfAny<'not any', 'foo', 'bar'>;
|
|
16
|
+
//=> 'bar'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
@category Type Guard
|
|
20
|
+
@category Utilities
|
|
21
|
+
*/
|
|
22
|
+
export type IfAny<T, TypeIfAny = true, TypeIfNotAny = false> = (
|
|
23
|
+
IsAny<T> extends true ? TypeIfAny : TypeIfNotAny
|
|
24
|
+
);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type {IsNever} from './is-never';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
An if-else-like type that resolves depending on whether the given type is `never`.
|
|
5
|
+
|
|
6
|
+
@see {@link IsNever}
|
|
7
|
+
|
|
8
|
+
@example
|
|
9
|
+
```
|
|
10
|
+
import type {IfNever} from 'type-fest';
|
|
11
|
+
|
|
12
|
+
type ShouldBeTrue = IfNever<never>;
|
|
13
|
+
//=> true
|
|
14
|
+
|
|
15
|
+
type ShouldBeBar = IfNever<'not never', 'foo', 'bar'>;
|
|
16
|
+
//=> 'bar'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
@category Type Guard
|
|
20
|
+
@category Utilities
|
|
21
|
+
*/
|
|
22
|
+
export type IfNever<T, TypeIfNever = true, TypeIfNotNever = false> = (
|
|
23
|
+
IsNever<T> extends true ? TypeIfNever : TypeIfNotNever
|
|
24
|
+
);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type {IsUnknown} from './is-unknown';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
An if-else-like type that resolves depending on whether the given type is `unknown`.
|
|
5
|
+
|
|
6
|
+
@see {@link IsUnknown}
|
|
7
|
+
|
|
8
|
+
@example
|
|
9
|
+
```
|
|
10
|
+
import type {IfUnknown} from 'type-fest';
|
|
11
|
+
|
|
12
|
+
type ShouldBeTrue = IfUnknown<unknown>;
|
|
13
|
+
//=> true
|
|
14
|
+
|
|
15
|
+
type ShouldBeBar = IfUnknown<'not unknown', 'foo', 'bar'>;
|
|
16
|
+
//=> 'bar'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
@category Type Guard
|
|
20
|
+
@category Utilities
|
|
21
|
+
*/
|
|
22
|
+
export type IfUnknown<T, TypeIfUnknown = true, TypeIfNotUnknown = false> = (
|
|
23
|
+
IsUnknown<T> extends true ? TypeIfUnknown : TypeIfNotUnknown
|
|
24
|
+
);
|
package/source/internal.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {Primitive} from './primitive';
|
|
2
2
|
import type {Simplify} from './simplify';
|
|
3
3
|
import type {Trim} from './trim';
|
|
4
|
+
import type {IsAny} from './is-any';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
Infer the length of the given array `<T>`.
|
|
@@ -158,23 +159,6 @@ export type IsNumeric<T extends string> = T extends `${number}`
|
|
|
158
159
|
: false
|
|
159
160
|
: false;
|
|
160
161
|
|
|
161
|
-
/**
|
|
162
|
-
Returns a boolean for whether the the type is `any`.
|
|
163
|
-
|
|
164
|
-
@link https://stackoverflow.com/a/49928360/1490091
|
|
165
|
-
*/
|
|
166
|
-
export type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
Returns a boolean for whether the the type is `never`.
|
|
170
|
-
*/
|
|
171
|
-
export type IsNever<T> = [T] extends [never] ? true : false;
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
Returns a boolean for whether the the type is `unknown`.
|
|
175
|
-
*/
|
|
176
|
-
export type IsUnknown<T> = IsNever<T> extends false ? T extends unknown ? unknown extends T ? IsAny<T> extends false ? true : false : false : false : false;
|
|
177
|
-
|
|
178
162
|
/**
|
|
179
163
|
For an object T, if it has any properties that are a union with `undefined`, make those into optional properties instead.
|
|
180
164
|
|
|
@@ -262,3 +246,8 @@ export type HasMultipleCallSignatures<T extends (...arguments: any[]) => unknown
|
|
|
262
246
|
Returns a boolean for whether the given `boolean` is not `false`.
|
|
263
247
|
*/
|
|
264
248
|
export type IsNotFalse<T extends boolean> = [T] extends [false] ? false : true;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
Returns a boolean for whether the given type is `null`.
|
|
252
|
+
*/
|
|
253
|
+
export type IsNull<T> = [T] extends [null] ? true : false;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Returns a boolean for whether the given type is `any`.
|
|
3
|
+
|
|
4
|
+
@link https://stackoverflow.com/a/49928360/1490091
|
|
5
|
+
|
|
6
|
+
Useful in type utilities, such as disallowing `any`s to be passed to a function.
|
|
7
|
+
|
|
8
|
+
@example
|
|
9
|
+
```
|
|
10
|
+
import type {IsAny} from 'type-fest';
|
|
11
|
+
|
|
12
|
+
const typedObject = {a: 1, b: 2} as const;
|
|
13
|
+
const anyObject: any = {a: 1, b: 2};
|
|
14
|
+
|
|
15
|
+
function get<O extends (IsAny<O> extends true ? {} : Record<string, number>), K extends keyof O = keyof O>(obj: O, key: K) {
|
|
16
|
+
return obj[key];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const typedA = get(typedObject, 'a');
|
|
20
|
+
//=> 1
|
|
21
|
+
|
|
22
|
+
const anyA = get(anyObject, 'a');
|
|
23
|
+
//=> any
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
@category Type Guard
|
|
27
|
+
@category Utilities
|
|
28
|
+
*/
|
|
29
|
+
export type IsAny<T> = 0 extends 1 & T ? true : false;
|
package/source/is-equal.d.ts
CHANGED
package/source/is-literal.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {Primitive} from './primitive';
|
|
2
2
|
import type {Numeric} from './numeric';
|
|
3
|
-
import type {
|
|
3
|
+
import type {IsNotFalse} from './internal';
|
|
4
|
+
import type {IsNever} from './is-never';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
Returns a boolean for whether the given type `T` is the specified `LiteralType`.
|
|
@@ -77,8 +78,8 @@ const output = capitalize('hello, world!');
|
|
|
77
78
|
//=> 'Hello, world!'
|
|
78
79
|
```
|
|
79
80
|
|
|
80
|
-
@category Utilities
|
|
81
81
|
@category Type Guard
|
|
82
|
+
@category Utilities
|
|
82
83
|
*/
|
|
83
84
|
export type IsStringLiteral<T> = LiteralCheck<T, string>;
|
|
84
85
|
|
|
@@ -125,8 +126,8 @@ endsWith('abc123', end);
|
|
|
125
126
|
//=> boolean
|
|
126
127
|
```
|
|
127
128
|
|
|
128
|
-
@category Utilities
|
|
129
129
|
@category Type Guard
|
|
130
|
+
@category Utilities
|
|
130
131
|
*/
|
|
131
132
|
export type IsNumericLiteral<T> = LiteralChecks<T, Numeric>;
|
|
132
133
|
|
|
@@ -165,8 +166,8 @@ const eitherId = getId({asString: runtimeBoolean});
|
|
|
165
166
|
//=> number | string
|
|
166
167
|
```
|
|
167
168
|
|
|
168
|
-
@category Utilities
|
|
169
169
|
@category Type Guard
|
|
170
|
+
@category Utilities
|
|
170
171
|
*/
|
|
171
172
|
export type IsBooleanLiteral<T> = LiteralCheck<T, boolean>;
|
|
172
173
|
|
|
@@ -200,8 +201,8 @@ get({[symbolValue]: 1} as const, symbolValue);
|
|
|
200
201
|
//=> number
|
|
201
202
|
```
|
|
202
203
|
|
|
203
|
-
@category Utilities
|
|
204
204
|
@category Type Guard
|
|
205
|
+
@category Utilities
|
|
205
206
|
*/
|
|
206
207
|
export type IsSymbolLiteral<T> = LiteralCheck<T, symbol>;
|
|
207
208
|
|
|
@@ -246,7 +247,7 @@ stripLeading(str, 'abc');
|
|
|
246
247
|
//=> string
|
|
247
248
|
```
|
|
248
249
|
|
|
249
|
-
@category Utilities
|
|
250
250
|
@category Type Guard
|
|
251
|
+
@category Utilities
|
|
251
252
|
*/
|
|
252
253
|
export type IsLiteral<T extends Primitive> = IsNotFalse<IsLiteralUnion<T>>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Returns a boolean for whether the given type is `never`.
|
|
3
|
+
|
|
4
|
+
@link https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919
|
|
5
|
+
@link https://stackoverflow.com/a/53984913/10292952
|
|
6
|
+
@link https://www.zhenghao.io/posts/ts-never
|
|
7
|
+
|
|
8
|
+
Useful in type utilities, such as checking if something does not occur.
|
|
9
|
+
|
|
10
|
+
@example
|
|
11
|
+
```
|
|
12
|
+
import type {IsNever} from 'type-fest';
|
|
13
|
+
|
|
14
|
+
type And<A, B> =
|
|
15
|
+
A extends true
|
|
16
|
+
? B extends true
|
|
17
|
+
? true
|
|
18
|
+
: false
|
|
19
|
+
: false;
|
|
20
|
+
|
|
21
|
+
// https://github.com/andnp/SimplyTyped/blob/master/src/types/strings.ts
|
|
22
|
+
type AreStringsEqual<A extends string, B extends string> =
|
|
23
|
+
And<
|
|
24
|
+
IsNever<Exclude<A, B>> extends true ? true : false,
|
|
25
|
+
IsNever<Exclude<B, A>> extends true ? true : false
|
|
26
|
+
>;
|
|
27
|
+
|
|
28
|
+
type EndIfEqual<I extends string, O extends string> =
|
|
29
|
+
AreStringsEqual<I, O> extends true
|
|
30
|
+
? never
|
|
31
|
+
: void;
|
|
32
|
+
|
|
33
|
+
function endIfEqual<I extends string, O extends string>(input: I, output: O): EndIfEqual<I, O> {
|
|
34
|
+
if (input === output) {
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
endIfEqual('abc', 'abc');
|
|
40
|
+
//=> never
|
|
41
|
+
|
|
42
|
+
endIfEqual('abc', '123');
|
|
43
|
+
//=> void
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
@category Type Guard
|
|
47
|
+
@category Utilities
|
|
48
|
+
*/
|
|
49
|
+
export type IsNever<T> = [T] extends [never] ? true : false;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type {IsNull} from './internal';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Returns a boolean for whether the given type is `unknown`.
|
|
5
|
+
|
|
6
|
+
@link https://github.com/dsherret/conditional-type-checks/pull/16
|
|
7
|
+
|
|
8
|
+
Useful in type utilities, such as when dealing with unknown data from API calls.
|
|
9
|
+
|
|
10
|
+
@example
|
|
11
|
+
```
|
|
12
|
+
import type {IsUnknown} from 'type-fest';
|
|
13
|
+
|
|
14
|
+
// https://github.com/pajecawav/tiny-global-store/blob/master/src/index.ts
|
|
15
|
+
type Action<TState, TPayload = void> =
|
|
16
|
+
IsUnknown<TPayload> extends true
|
|
17
|
+
? (state: TState) => TState,
|
|
18
|
+
: (state: TState, payload: TPayload) => TState;
|
|
19
|
+
|
|
20
|
+
class Store<TState> {
|
|
21
|
+
constructor(private state: TState) {}
|
|
22
|
+
|
|
23
|
+
execute<TPayload = void>(action: Action<TState, TPayload>, payload?: TPayload): TState {
|
|
24
|
+
this.state = action(this.state, payload);
|
|
25
|
+
return this.state;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ... other methods
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const store = new Store({value: 1});
|
|
32
|
+
declare const someExternalData: unknown;
|
|
33
|
+
|
|
34
|
+
store.execute(state => ({value: state.value + 1}));
|
|
35
|
+
//=> `TPayload` is `void`
|
|
36
|
+
|
|
37
|
+
store.execute((state, payload) => ({value: state.value + payload}), 5);
|
|
38
|
+
//=> `TPayload` is `5`
|
|
39
|
+
|
|
40
|
+
store.execute((state, payload) => ({value: state.value + payload}), someExternalData);
|
|
41
|
+
//=> Errors: `action` is `(state: TState) => TState`
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
@category Utilities
|
|
45
|
+
*/
|
|
46
|
+
export type IsUnknown<T> = (
|
|
47
|
+
unknown extends T // `T` can be `unknown` or `any`
|
|
48
|
+
? IsNull<T> extends false // `any` can be `null`, but `unknown` can't be
|
|
49
|
+
? true
|
|
50
|
+
: false
|
|
51
|
+
: false
|
|
52
|
+
);
|
package/source/join.d.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
// The builtin `join` method supports all these natively in the same way that typescript handles them so we can safely accept all of them.
|
|
2
|
+
type JoinableItem = string | number | bigint | boolean | undefined | null;
|
|
3
|
+
|
|
4
|
+
// `null` and `undefined` are treated uniquely in the built-in join method, in a way that differs from the default `toString` that would result in the type `${undefined}`. That's why we need to handle it specifically with this helper.
|
|
5
|
+
// @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join#description
|
|
6
|
+
type NullishCoalesce<
|
|
7
|
+
Value extends JoinableItem,
|
|
8
|
+
Fallback extends string,
|
|
9
|
+
> = Value extends undefined | null ? NonNullable<Value> | Fallback : Value;
|
|
10
|
+
|
|
1
11
|
/**
|
|
2
12
|
Join an array of strings and/or numbers using the given string as a delimiter.
|
|
3
13
|
|
|
@@ -15,21 +25,44 @@ const path: Join<['foo', 'bar', 'baz'], '.'> = ['foo', 'bar', 'baz'].join('.');
|
|
|
15
25
|
|
|
16
26
|
// Only number items; result is: '1.2.3'
|
|
17
27
|
const path: Join<[1, 2, 3], '.'> = [1, 2, 3].join('.');
|
|
28
|
+
|
|
29
|
+
// Only bigint items; result is '1.2.3'
|
|
30
|
+
const path: Join<[1n, 2n, 3n], '.'> = [1n, 2n, 3n].join('.');
|
|
31
|
+
|
|
32
|
+
// Only boolean items; result is: 'true.false.true'
|
|
33
|
+
const path: Join<[true, false, true], '.'> = [true, false, true].join('.');
|
|
34
|
+
|
|
35
|
+
// Contains nullish items; result is: 'foo..baz..xyz'
|
|
36
|
+
const path: Join<['foo', undefined, 'baz', null, 'xyz'], '.'> = ['foo', undefined, 'baz', null, 'xyz'].join('.');
|
|
37
|
+
|
|
38
|
+
// Partial tuple shapes (rest param last); result is: `prefix.${string}`
|
|
39
|
+
const path: Join<['prefix', ...string[]], '.'> = ['prefix'].join('.');
|
|
40
|
+
|
|
41
|
+
// Partial tuple shapes (rest param first); result is: `${string}.suffix`
|
|
42
|
+
const path: Join<[...string[], 'suffix'], '.'> = ['suffix'].join('.');
|
|
43
|
+
|
|
44
|
+
// Tuples items with nullish unions; result is '.' | 'hello.' | '.world' | 'hello.world'
|
|
45
|
+
const path: Join<['hello' | undefined, 'world' | null], '.'> = ['hello', 'world'].join('.');
|
|
18
46
|
```
|
|
19
47
|
|
|
20
48
|
@category Array
|
|
21
49
|
@category Template literal
|
|
22
50
|
*/
|
|
23
51
|
export type Join<
|
|
24
|
-
|
|
52
|
+
Items extends readonly JoinableItem[],
|
|
25
53
|
Delimiter extends string,
|
|
26
|
-
> =
|
|
54
|
+
> = Items extends []
|
|
27
55
|
? ''
|
|
28
|
-
:
|
|
29
|
-
? `${
|
|
30
|
-
:
|
|
31
|
-
|
|
32
|
-
...infer
|
|
56
|
+
: Items extends readonly [JoinableItem?]
|
|
57
|
+
? `${NullishCoalesce<Items[0], ''>}`
|
|
58
|
+
: Items extends readonly [
|
|
59
|
+
infer First extends JoinableItem,
|
|
60
|
+
...infer Tail extends readonly JoinableItem[],
|
|
33
61
|
]
|
|
34
|
-
? `${
|
|
35
|
-
:
|
|
62
|
+
? `${NullishCoalesce<First, ''>}${Delimiter}${Join<Tail, Delimiter>}`
|
|
63
|
+
: Items extends readonly [
|
|
64
|
+
...infer Head extends readonly JoinableItem[],
|
|
65
|
+
infer Last extends JoinableItem,
|
|
66
|
+
]
|
|
67
|
+
? `${Join<Head, Delimiter>}${Delimiter}${NullishCoalesce<Last, ''>}`
|
|
68
|
+
: string;
|
package/source/jsonify.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type {JsonPrimitive, JsonValue} from './basic';
|
|
2
2
|
import type {EmptyObject} from './empty-object';
|
|
3
|
-
import type {
|
|
3
|
+
import type {UndefinedToOptional} from './internal';
|
|
4
4
|
import type {NegativeInfinity, PositiveInfinity} from './numeric';
|
|
5
5
|
import type {TypedArray} from './typed-array';
|
|
6
|
+
import type {IsAny} from './is-any';
|
|
6
7
|
|
|
7
8
|
// Note: The return value has to be `any` and not `unknown` so it can match `void`.
|
|
8
9
|
type NotJsonable = ((...arguments_: any[]) => any) | undefined | symbol;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type {LiteralToPrimitive} from './literal-to-primitive';
|
|
2
|
+
import type {OmitIndexSignature} from './omit-index-signature';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
Like `LiteralToPrimitive` except it converts literal types inside an object or array deeply.
|
|
6
|
+
|
|
7
|
+
For example, given a constant object, it returns a new object type with the same keys but with all the values converted to primitives.
|
|
8
|
+
|
|
9
|
+
@see LiteralToPrimitive
|
|
10
|
+
|
|
11
|
+
Use-case: Deal with data that is imported from a JSON file.
|
|
12
|
+
|
|
13
|
+
@example
|
|
14
|
+
```
|
|
15
|
+
import type {LiteralToPrimitiveDeep, TsConfigJson} from 'type-fest';
|
|
16
|
+
import tsconfig from 'path/to/tsconfig.json';
|
|
17
|
+
|
|
18
|
+
function doSomethingWithTSConfig(config: LiteralToPrimitiveDeep<TsConfigJson>) { ... }
|
|
19
|
+
|
|
20
|
+
// No casting is needed to pass the type check
|
|
21
|
+
doSomethingWithTSConfig(tsconfig);
|
|
22
|
+
|
|
23
|
+
// If LiteralToPrimitiveDeep is not used, you need to cast the imported data like this:
|
|
24
|
+
doSomethingWithTSConfig(tsconfig as TsConfigJson);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
@category Type
|
|
28
|
+
@category Object
|
|
29
|
+
*/
|
|
30
|
+
export type LiteralToPrimitiveDeep<T> = T extends object
|
|
31
|
+
? T extends Array<infer U>
|
|
32
|
+
? Array<LiteralToPrimitiveDeep<U>>
|
|
33
|
+
: {
|
|
34
|
+
[K in keyof OmitIndexSignature<T>]: LiteralToPrimitiveDeep<T[K]>;
|
|
35
|
+
}
|
|
36
|
+
: LiteralToPrimitive<T>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type {Merge} from './merge';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Override existing properties of the given type. Similar to `Merge`, but enforces that the original type has the properties you want to override.
|
|
5
|
+
|
|
6
|
+
This is useful when you want to override existing properties with a different type and make sure that these properties really exist in the original.
|
|
7
|
+
|
|
8
|
+
@example
|
|
9
|
+
```
|
|
10
|
+
type Foo = {
|
|
11
|
+
a: string
|
|
12
|
+
b: string
|
|
13
|
+
}
|
|
14
|
+
type Bar = OverrideProperties<Foo, {b: number}>
|
|
15
|
+
//=> {a: string, b: number}
|
|
16
|
+
|
|
17
|
+
type Baz = OverrideProperties<Foo, {c: number}>
|
|
18
|
+
// error TS2559: Type '{c: number}' has no properties in common with type 'Partial{a: unknown; b: unknown}>'.
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
@category Object
|
|
22
|
+
*/
|
|
23
|
+
export type OverrideProperties<
|
|
24
|
+
TOriginal,
|
|
25
|
+
TOverride extends Partial<{[key in keyof TOriginal]: unknown}>,
|
|
26
|
+
> = Merge<TOriginal, TOverride>;
|