type-fest 2.15.1 → 2.18.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 -2
- package/package.json +1 -1
- package/readme.md +10 -39
- package/source/camel-case.d.ts +1 -1
- package/source/delimiter-case.d.ts +1 -1
- package/source/get.d.ts +1 -1
- package/source/has-optional-keys.d.ts +21 -0
- package/source/has-required-keys.d.ts +59 -0
- package/source/includes.d.ts +5 -5
- package/source/internal.d.ts +6 -0
- package/source/optional-keys-of.d.ts +38 -0
- package/source/partial-deep.d.ts +48 -16
- package/source/partial-on-undefined-deep.d.ts +70 -0
- package/source/replace.d.ts +1 -1
- package/source/required-keys-of.d.ts +29 -0
- package/source/simplify.d.ts +26 -1
- package/source/spread.d.ts +54 -0
- package/source/utilities.d.ts +0 -5
package/index.d.ts
CHANGED
|
@@ -14,7 +14,8 @@ export {RequireAtLeastOne} from './source/require-at-least-one';
|
|
|
14
14
|
export {RequireExactlyOne} from './source/require-exactly-one';
|
|
15
15
|
export {RequireAllOrNone} from './source/require-all-or-none';
|
|
16
16
|
export {RemoveIndexSignature} from './source/remove-index-signature';
|
|
17
|
-
export {PartialDeep} from './source/partial-deep';
|
|
17
|
+
export {PartialDeep, PartialDeepOptions} from './source/partial-deep';
|
|
18
|
+
export {PartialOnUndefinedDeep, PartialOnUndefinedDeepOptions} from './source/partial-on-undefined-deep';
|
|
18
19
|
export {ReadonlyDeep} from './source/readonly-deep';
|
|
19
20
|
export {LiteralUnion} from './source/literal-union';
|
|
20
21
|
export {Promisable} from './source/promisable';
|
|
@@ -38,7 +39,7 @@ export {Entry} from './source/entry';
|
|
|
38
39
|
export {Entries} from './source/entries';
|
|
39
40
|
export {SetReturnType} from './source/set-return-type';
|
|
40
41
|
export {Asyncify} from './source/asyncify';
|
|
41
|
-
export {Simplify} from './source/simplify';
|
|
42
|
+
export {Simplify, SimplifyOptions} from './source/simplify';
|
|
42
43
|
export {Jsonify} from './source/jsonify';
|
|
43
44
|
export {Schema} from './source/schema';
|
|
44
45
|
export {LiteralToPrimitive} from './source/literal-to-primitive';
|
|
@@ -57,6 +58,11 @@ export {
|
|
|
57
58
|
export {StringKeyOf} from './source/string-key-of';
|
|
58
59
|
export {Exact} from './source/exact';
|
|
59
60
|
export {ReadonlyTuple} from './source/readonly-tuple';
|
|
61
|
+
export {OptionalKeysOf} from './source/optional-keys-of';
|
|
62
|
+
export {HasOptionalKeys} from './source/has-optional-keys';
|
|
63
|
+
export {RequiredKeysOf} from './source/required-keys-of';
|
|
64
|
+
export {HasRequiredKeys} from './source/has-required-keys';
|
|
65
|
+
export {Spread} from './source/spread';
|
|
60
66
|
|
|
61
67
|
// Template literal types
|
|
62
68
|
export {CamelCase} from './source/camel-case';
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -40,41 +40,6 @@
|
|
|
40
40
|
<br>
|
|
41
41
|
<br>
|
|
42
42
|
<br>
|
|
43
|
-
<a href="https://neverinstall.com/spaces/devtools?utm_source=github&utm_medium=sponsor&utm_campaign=sindre#gh-light-mode-only">
|
|
44
|
-
<div>
|
|
45
|
-
<img src="https://sindresorhus.com/assets/thanks/neverinstall-logo-light.svg" width="200" alt="neverinstall">
|
|
46
|
-
</div>
|
|
47
|
-
<br>
|
|
48
|
-
<b>All your favourite IDE's now available on the cloud</b>
|
|
49
|
-
<div>
|
|
50
|
-
<sub>
|
|
51
|
-
Neverinstall gives you an uninterrupted development experience and improved accessibility,
|
|
52
|
-
<br>
|
|
53
|
-
allowing you to code faster, better and on-the-go on your favourite IDEs like
|
|
54
|
-
<br>
|
|
55
|
-
Android Studio, VS Code, Jupyter and PyCharm using your browser.
|
|
56
|
-
</sub>
|
|
57
|
-
</div>
|
|
58
|
-
</a>
|
|
59
|
-
<a href="https://neverinstall.com/spaces/devtools?utm_source=github&utm_medium=sponsor&utm_campaign=sindre#gh-dark-mode-only">
|
|
60
|
-
<div>
|
|
61
|
-
<img src="https://sindresorhus.com/assets/thanks/neverinstall-logo-dark.svg" width="200" alt="neverinstall">
|
|
62
|
-
</div>
|
|
63
|
-
<br>
|
|
64
|
-
<b>All your favourite IDE's now available on the cloud</b>
|
|
65
|
-
<div>
|
|
66
|
-
<sub>
|
|
67
|
-
Neverinstall gives you an uninterrupted development experience and improved accessibility,
|
|
68
|
-
<br>
|
|
69
|
-
allowing you to code faster, better and on-the-go on your favourite IDEs like
|
|
70
|
-
<br>
|
|
71
|
-
Android Studio, VS Code, Jupyter and PyCharm using your browser.
|
|
72
|
-
</sub>
|
|
73
|
-
</div>
|
|
74
|
-
</a>
|
|
75
|
-
<br>
|
|
76
|
-
<br>
|
|
77
|
-
<br>
|
|
78
43
|
<a href="https://www.useanvil.com/?utm_source=sindresorhus#gh-light-mode-only">
|
|
79
44
|
<div>
|
|
80
45
|
<img src="https://sindresorhus.com/assets/thanks/anvil-logo-light.svg" width="200" alt="Anvil">
|
|
@@ -169,6 +134,7 @@ Click the type names for complete docs.
|
|
|
169
134
|
- [`RequireAllOrNone`](source/require-all-or-none.d.ts) - Create a type that requires all of the given keys or none of the given keys.
|
|
170
135
|
- [`RemoveIndexSignature`](source/remove-index-signature.d.ts) - Create a type that only has explicitly defined properties, absent of any index signatures.
|
|
171
136
|
- [`PartialDeep`](source/partial-deep.d.ts) - Create a deeply optional version of another type. Use [`Partial<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype) if you only need one level deep.
|
|
137
|
+
- [`PartialOnUndefinedDeep`](source/partial-on-undefined-deep.d.ts) - Create a deep version of another type where all keys accepting `undefined` type are set to optional.
|
|
172
138
|
- [`ReadonlyDeep`](source/readonly-deep.d.ts) - Create a deeply immutable version of an `object`/`Map`/`Set`/`Array` type. Use [`Readonly<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype) if you only need one level deep.
|
|
173
139
|
- [`LiteralUnion`](source/literal-union.d.ts) - Create a union type by combining primitive types and literal types without sacrificing auto-completion in IDEs for the literal type part of the union. Workaround for [Microsoft/TypeScript#29729](https://github.com/Microsoft/TypeScript/issues/29729).
|
|
174
140
|
- [`Opaque`](source/opaque.d.ts) - Create an [opaque type](https://codemix.com/opaque-types-in-javascript/).
|
|
@@ -192,6 +158,11 @@ Click the type names for complete docs.
|
|
|
192
158
|
- [`StringKeyOf`](source/string-key-of.d.ts) - Get keys of the given type as strings.
|
|
193
159
|
- [`Schema`](source/schema.d.ts) - Create a deep version of another object type where property values are recursively replaced into a given value type.
|
|
194
160
|
- [`Exact`](source/exact.d.ts) - Create a type that does not allow extra properties.
|
|
161
|
+
- [`OptionalKeysOf`](source/optional-keys-of.d.ts) - Extract all optional keys from the given type.
|
|
162
|
+
- [`HasOptionalKeys`](source/has-optional-keys.d.ts) - Create a `true`/`false` type depending on whether the given type has any optional fields.
|
|
163
|
+
- [`RequiredKeysOf`](source/required-keys-of.d.ts) - Extract all required keys from the given type.
|
|
164
|
+
- [`HasRequiredKeys`](source/has-required-keys.d.ts) - Create a `true`/`false` type depending on whether the given type has any required fields.
|
|
165
|
+
- [`Spread`](source/spread.d.ts) - Mimic the type inferred by TypeScript when merging two objects using the spread operator.
|
|
195
166
|
|
|
196
167
|
### JSON
|
|
197
168
|
|
|
@@ -835,7 +806,7 @@ There are many advanced types most users don't know about.
|
|
|
835
806
|
type T2 = Uppercase<'foo' | 'bar'>; // 'FOO' | 'BAR'
|
|
836
807
|
|
|
837
808
|
type T3<S extends string> = Uppercase<`aB${S}`>;
|
|
838
|
-
type T4 =
|
|
809
|
+
type T4 = T3<'xYz'>; // 'ABXYZ'
|
|
839
810
|
|
|
840
811
|
type T5 = Uppercase<string>; // string
|
|
841
812
|
type T6 = Uppercase<any>; // any
|
|
@@ -856,7 +827,7 @@ There are many advanced types most users don't know about.
|
|
|
856
827
|
type T2 = Lowercase<'FOO' | 'BAR'>; // 'foo' | 'bar'
|
|
857
828
|
|
|
858
829
|
type T3<S extends string> = Lowercase<`aB${S}`>;
|
|
859
|
-
type T4 =
|
|
830
|
+
type T4 = T3<'xYz'>; // 'abxyz'
|
|
860
831
|
|
|
861
832
|
type T5 = Lowercase<string>; // string
|
|
862
833
|
type T6 = Lowercase<any>; // any
|
|
@@ -877,7 +848,7 @@ There are many advanced types most users don't know about.
|
|
|
877
848
|
type T2 = Capitalize<'foo' | 'bar'>; // 'Foo' | 'Bar'
|
|
878
849
|
|
|
879
850
|
type T3<S extends string> = Capitalize<`aB${S}`>;
|
|
880
|
-
type T4 =
|
|
851
|
+
type T4 = T3<'xYz'>; // 'ABxYz'
|
|
881
852
|
|
|
882
853
|
type T5 = Capitalize<string>; // string
|
|
883
854
|
type T6 = Capitalize<any>; // any
|
|
@@ -898,7 +869,7 @@ There are many advanced types most users don't know about.
|
|
|
898
869
|
type T2 = Uncapitalize<'Foo' | 'Bar'>; // 'foo' | 'bar'
|
|
899
870
|
|
|
900
871
|
type T3<S extends string> = Uncapitalize<`AB${S}`>;
|
|
901
|
-
type T4 =
|
|
872
|
+
type T4 = T3<'xYz'>; // 'aBxYz'
|
|
902
873
|
|
|
903
874
|
type T5 = Uncapitalize<string>; // string
|
|
904
875
|
type T6 = Uncapitalize<any>; // any
|
package/source/camel-case.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {UpperCaseCharacters, WordSeparators} from '../source/
|
|
1
|
+
import type {UpperCaseCharacters, WordSeparators} from '../source/internal';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
Unlike a simpler split, this one includes the delimiter splitted on in the resulting array literal. This is to enable splitting on, for example, upper-case characters.
|
package/source/get.d.ts
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {OptionalKeysOf} from './optional-keys-of';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Creates a type that represents `true` or `false` depending on whether the given type has any optional fields.
|
|
5
|
+
|
|
6
|
+
This is useful when you want to create an API whose behavior depends on the presence or absence of optional fields.
|
|
7
|
+
|
|
8
|
+
@example
|
|
9
|
+
```
|
|
10
|
+
import type {HasOptionalKeys, OptionalKeysOf} from 'type-fest';
|
|
11
|
+
|
|
12
|
+
type UpdateService<Entity extends object> = {
|
|
13
|
+
removeField: HasOptionalKeys<Entity> extends true
|
|
14
|
+
? (field: OptionalKeysOf<Entity>) => Promise<void>
|
|
15
|
+
: never
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
@category Utilities
|
|
20
|
+
*/
|
|
21
|
+
export type HasOptionalKeys<BaseType extends object> = OptionalKeysOf<BaseType> extends never ? false : true;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {RequiredKeysOf} from './required-keys-of';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Creates a type that represents `true` or `false` depending on whether the given type has any required fields.
|
|
5
|
+
|
|
6
|
+
This is useful when you want to create an API whose behavior depends on the presence or absence of required fields.
|
|
7
|
+
|
|
8
|
+
@example
|
|
9
|
+
```
|
|
10
|
+
import type {HasRequiredKeys} from 'type-fest';
|
|
11
|
+
|
|
12
|
+
type GeneratorOptions<Template extends object> = {
|
|
13
|
+
prop1: number;
|
|
14
|
+
prop2: string;
|
|
15
|
+
} & (HasRequiredKeys<Template> extends true
|
|
16
|
+
? {template: Template}
|
|
17
|
+
: {template?: Template});
|
|
18
|
+
|
|
19
|
+
interface Template1 {
|
|
20
|
+
optionalSubParam?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface Template2 {
|
|
24
|
+
requiredSubParam: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
type Options1 = GeneratorOptions<Template1>;
|
|
28
|
+
type Options2 = GeneratorOptions<Template2>;
|
|
29
|
+
|
|
30
|
+
const optA: Options1 = {
|
|
31
|
+
prop1: 0,
|
|
32
|
+
prop2: 'hi'
|
|
33
|
+
};
|
|
34
|
+
const optB: Options1 = {
|
|
35
|
+
prop1: 0,
|
|
36
|
+
prop2: 'hi',
|
|
37
|
+
template: {}
|
|
38
|
+
};
|
|
39
|
+
const optC: Options1 = {
|
|
40
|
+
prop1: 0,
|
|
41
|
+
prop2: 'hi',
|
|
42
|
+
template: {
|
|
43
|
+
optionalSubParam: 'optional value'
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const optD: Options2 = {
|
|
48
|
+
prop1: 0,
|
|
49
|
+
prop2: 'hi',
|
|
50
|
+
template: {
|
|
51
|
+
requiredSubParam: 'required value'
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
@category Utilities
|
|
58
|
+
*/
|
|
59
|
+
export type HasRequiredKeys<BaseType extends object> = RequiredKeysOf<BaseType> extends never ? false : true;
|
package/source/includes.d.ts
CHANGED
|
@@ -15,8 +15,8 @@ type hasRed<array extends any[]> = Includes<array, 'red'>;
|
|
|
15
15
|
@category Array
|
|
16
16
|
*/
|
|
17
17
|
export type Includes<Value extends readonly any[], Item> =
|
|
18
|
-
|
|
19
|
-
? true
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
Value extends readonly [Value[0], ...infer rest]
|
|
19
|
+
? IsEqual<Value[0], Item> extends true
|
|
20
|
+
? true
|
|
21
|
+
: Includes<rest, Item>
|
|
22
|
+
: false;
|
package/source/internal.d.ts
CHANGED
|
@@ -51,3 +51,9 @@ The reason a simple `keyof Union` does not work is because `keyof` always return
|
|
|
51
51
|
@link https://stackoverflow.com/a/49402091
|
|
52
52
|
*/
|
|
53
53
|
export type KeysOfUnion<T> = T extends T ? keyof T : never;
|
|
54
|
+
|
|
55
|
+
export type UpperCaseCharacters = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';
|
|
56
|
+
|
|
57
|
+
export type WordSeparators = '-' | '_' | ' ';
|
|
58
|
+
|
|
59
|
+
export type StringDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Extract all optional keys from the given type.
|
|
3
|
+
|
|
4
|
+
This is useful when you want to create a new type that contains different type values for the optional keys only.
|
|
5
|
+
|
|
6
|
+
@example
|
|
7
|
+
```
|
|
8
|
+
import type {OptionalKeysOf, Except} from 'type-fest';
|
|
9
|
+
|
|
10
|
+
interface User {
|
|
11
|
+
name: string;
|
|
12
|
+
surname: string;
|
|
13
|
+
|
|
14
|
+
luckyNumber?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const REMOVE_FIELD = Symbol('remove field symbol');
|
|
18
|
+
type UpdateOperation<Entity extends object> = Except<Partial<Entity>, OptionalKeysOf<Entity>> & {
|
|
19
|
+
[Key in OptionalKeysOf<Entity>]?: Entity[Key] | typeof REMOVE_FIELD;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const update1: UpdateOperation<User> = {
|
|
23
|
+
name: 'Alice'
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const update2: UpdateOperation<User> = {
|
|
27
|
+
name: 'Bob',
|
|
28
|
+
luckyNumber: REMOVE_FIELD
|
|
29
|
+
};
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
@category Utilities
|
|
33
|
+
*/
|
|
34
|
+
export type OptionalKeysOf<BaseType extends object> = Exclude<{
|
|
35
|
+
[Key in keyof BaseType]: BaseType extends Record<Key, BaseType[Key]>
|
|
36
|
+
? never
|
|
37
|
+
: Key
|
|
38
|
+
}[keyof BaseType], undefined>;
|
package/source/partial-deep.d.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import type {BuiltIns} from './internal';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
@see PartialDeep
|
|
5
|
+
*/
|
|
6
|
+
export interface PartialDeepOptions {
|
|
7
|
+
/**
|
|
8
|
+
Whether to affect the individual elements of arrays and tuples.
|
|
9
|
+
|
|
10
|
+
@default true
|
|
11
|
+
*/
|
|
12
|
+
readonly recurseIntoArrays?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
3
15
|
/**
|
|
4
16
|
Create a type from another type with all keys and nested keys set to optional.
|
|
5
17
|
|
|
@@ -28,54 +40,74 @@ const applySavedSettings = (savedSettings: PartialDeep<Settings>) => {
|
|
|
28
40
|
settings = applySavedSettings({textEditor: {fontWeight: 500}});
|
|
29
41
|
```
|
|
30
42
|
|
|
43
|
+
By default, this also affects array and tuple types:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
import type {PartialDeep} from 'type-fest';
|
|
47
|
+
|
|
48
|
+
interface Settings {
|
|
49
|
+
languages: string[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const partialSettings: PartialDeep<Settings> = {
|
|
53
|
+
languages: [undefined]
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If this is undesirable, you can pass `{recurseIntoArrays: false}` as the second type argument.
|
|
58
|
+
|
|
31
59
|
@category Object
|
|
32
60
|
@category Array
|
|
33
61
|
@category Set
|
|
34
62
|
@category Map
|
|
35
63
|
*/
|
|
36
|
-
export type PartialDeep<T> = T extends BuiltIns
|
|
64
|
+
export type PartialDeep<T, Options extends PartialDeepOptions = {}> = T extends BuiltIns
|
|
37
65
|
? T
|
|
38
66
|
: T extends Map<infer KeyType, infer ValueType>
|
|
39
|
-
? PartialMapDeep<KeyType, ValueType>
|
|
67
|
+
? PartialMapDeep<KeyType, ValueType, Options>
|
|
40
68
|
: T extends Set<infer ItemType>
|
|
41
|
-
? PartialSetDeep<ItemType>
|
|
69
|
+
? PartialSetDeep<ItemType, Options>
|
|
42
70
|
: T extends ReadonlyMap<infer KeyType, infer ValueType>
|
|
43
|
-
? PartialReadonlyMapDeep<KeyType, ValueType>
|
|
71
|
+
? PartialReadonlyMapDeep<KeyType, ValueType, Options>
|
|
44
72
|
: T extends ReadonlySet<infer ItemType>
|
|
45
|
-
? PartialReadonlySetDeep<ItemType>
|
|
73
|
+
? PartialReadonlySetDeep<ItemType, Options>
|
|
46
74
|
: T extends ((...arguments: any[]) => unknown)
|
|
47
75
|
? T | undefined
|
|
48
76
|
: T extends object
|
|
49
|
-
? T extends
|
|
50
|
-
?
|
|
51
|
-
?
|
|
52
|
-
:
|
|
53
|
-
|
|
77
|
+
? T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
|
|
78
|
+
? Options['recurseIntoArrays'] extends false // If they opt out of array testing, just use the original type
|
|
79
|
+
? T
|
|
80
|
+
: ItemType[] extends T // Test for arrays (non-tuples) specifically
|
|
81
|
+
? readonly ItemType[] extends T // Differentiate readonly and mutable arrays
|
|
82
|
+
? ReadonlyArray<PartialDeep<ItemType | undefined, Options>>
|
|
83
|
+
: Array<PartialDeep<ItemType | undefined, Options>>
|
|
84
|
+
: PartialObjectDeep<T, Options> // Tuples behave properly
|
|
85
|
+
: PartialObjectDeep<T, Options>
|
|
54
86
|
: unknown;
|
|
55
87
|
|
|
56
88
|
/**
|
|
57
89
|
Same as `PartialDeep`, but accepts only `Map`s and as inputs. Internal helper for `PartialDeep`.
|
|
58
90
|
*/
|
|
59
|
-
interface PartialMapDeep<KeyType, ValueType> extends Map<PartialDeep<KeyType>, PartialDeep<ValueType>> {}
|
|
91
|
+
interface PartialMapDeep<KeyType, ValueType, Options extends PartialDeepOptions> extends Map<PartialDeep<KeyType, Options>, PartialDeep<ValueType, Options>> {}
|
|
60
92
|
|
|
61
93
|
/**
|
|
62
94
|
Same as `PartialDeep`, but accepts only `Set`s as inputs. Internal helper for `PartialDeep`.
|
|
63
95
|
*/
|
|
64
|
-
interface PartialSetDeep<T> extends Set<PartialDeep<T>> {}
|
|
96
|
+
interface PartialSetDeep<T, Options extends PartialDeepOptions> extends Set<PartialDeep<T, Options>> {}
|
|
65
97
|
|
|
66
98
|
/**
|
|
67
99
|
Same as `PartialDeep`, but accepts only `ReadonlyMap`s as inputs. Internal helper for `PartialDeep`.
|
|
68
100
|
*/
|
|
69
|
-
interface PartialReadonlyMapDeep<KeyType, ValueType> extends ReadonlyMap<PartialDeep<KeyType>, PartialDeep<ValueType>> {}
|
|
101
|
+
interface PartialReadonlyMapDeep<KeyType, ValueType, Options extends PartialDeepOptions> extends ReadonlyMap<PartialDeep<KeyType, Options>, PartialDeep<ValueType, Options>> {}
|
|
70
102
|
|
|
71
103
|
/**
|
|
72
104
|
Same as `PartialDeep`, but accepts only `ReadonlySet`s as inputs. Internal helper for `PartialDeep`.
|
|
73
105
|
*/
|
|
74
|
-
interface PartialReadonlySetDeep<T> extends ReadonlySet<PartialDeep<T>> {}
|
|
106
|
+
interface PartialReadonlySetDeep<T, Options extends PartialDeepOptions> extends ReadonlySet<PartialDeep<T, Options>> {}
|
|
75
107
|
|
|
76
108
|
/**
|
|
77
109
|
Same as `PartialDeep`, but accepts only `object`s as inputs. Internal helper for `PartialDeep`.
|
|
78
110
|
*/
|
|
79
|
-
type PartialObjectDeep<ObjectType extends object> = {
|
|
80
|
-
[KeyType in keyof ObjectType]?: PartialDeep<ObjectType[KeyType]>
|
|
111
|
+
type PartialObjectDeep<ObjectType extends object, Options extends PartialDeepOptions> = {
|
|
112
|
+
[KeyType in keyof ObjectType]?: PartialDeep<ObjectType[KeyType], Options>
|
|
81
113
|
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type {BuiltIns} from './internal';
|
|
2
|
+
import type {Merge} from './merge';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
@see PartialOnUndefinedDeep
|
|
6
|
+
*/
|
|
7
|
+
export interface PartialOnUndefinedDeepOptions {
|
|
8
|
+
/**
|
|
9
|
+
Whether to affect the individual elements of arrays and tuples.
|
|
10
|
+
|
|
11
|
+
@default false
|
|
12
|
+
*/
|
|
13
|
+
readonly recurseIntoArrays?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
Create a deep version of another type where all keys accepting `undefined` type are set to optional.
|
|
18
|
+
|
|
19
|
+
This utility type is recursive, transforming at any level deep. By default, it does not affect arrays and tuples items unless you explicitly pass `{recurseIntoArrays: true}` as the second type argument.
|
|
20
|
+
|
|
21
|
+
Use-cases:
|
|
22
|
+
- Make all properties of a type that can be undefined optional to not have to specify keys with undefined value.
|
|
23
|
+
|
|
24
|
+
@example
|
|
25
|
+
```
|
|
26
|
+
import type {PartialOnUndefinedDeep} from 'type-fest';
|
|
27
|
+
|
|
28
|
+
interface Settings {
|
|
29
|
+
optionA: string;
|
|
30
|
+
optionB: number | undefined;
|
|
31
|
+
subOption: {
|
|
32
|
+
subOptionA: boolean;
|
|
33
|
+
subOptionB: boolean | undefined;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const testSettings: PartialOnUndefinedDeep<Settings> = {
|
|
38
|
+
optionA: 'foo',
|
|
39
|
+
// 👉 optionB is now optional and can be omitted
|
|
40
|
+
subOption: {
|
|
41
|
+
subOptionA: true,
|
|
42
|
+
// 👉 subOptionB is now optional as well and can be omitted
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
@category Object
|
|
48
|
+
*/
|
|
49
|
+
export type PartialOnUndefinedDeep<T, Options extends PartialOnUndefinedDeepOptions = {}> = T extends Record<any, any> | undefined
|
|
50
|
+
? {[KeyType in keyof T as undefined extends T[KeyType] ? KeyType : never]?: PartialOnUndefinedDeepValue<T[KeyType], Options>} extends infer U // Make a partial type with all value types accepting undefined (and set them optional)
|
|
51
|
+
? Merge<{[KeyType in keyof T as KeyType extends keyof U ? never : KeyType]: PartialOnUndefinedDeepValue<T[KeyType], Options>}, U> // Join all remaining keys not treated in U
|
|
52
|
+
: never // Should not happen
|
|
53
|
+
: T;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
Utility type to get the value type by key and recursively call `PartialOnUndefinedDeep` to transform sub-objects.
|
|
57
|
+
*/
|
|
58
|
+
type PartialOnUndefinedDeepValue<T, Options extends PartialOnUndefinedDeepOptions> = T extends BuiltIns | ((...arguments: any[]) => unknown)
|
|
59
|
+
? T
|
|
60
|
+
: T extends ReadonlyArray<infer U> // Test if type is array or tuple
|
|
61
|
+
? Options['recurseIntoArrays'] extends true // Check if option is activated
|
|
62
|
+
? U[] extends T // Check if array not tuple
|
|
63
|
+
? readonly U[] extends T
|
|
64
|
+
? ReadonlyArray<PartialOnUndefinedDeep<U, Options>> // Readonly array treatment
|
|
65
|
+
: Array<PartialOnUndefinedDeep<U, Options>> // Mutable array treatment
|
|
66
|
+
: PartialOnUndefinedDeep<{[Key in keyof T]: PartialOnUndefinedDeep<T[Key], Options>}, Options> // Tuple treatment
|
|
67
|
+
: T
|
|
68
|
+
: T extends Record<any, any> | undefined
|
|
69
|
+
? PartialOnUndefinedDeep<T, Options>
|
|
70
|
+
: unknown;
|
package/source/replace.d.ts
CHANGED
|
@@ -62,6 +62,6 @@ export type Replace<
|
|
|
62
62
|
Options extends ReplaceOptions = {},
|
|
63
63
|
> = Input extends `${infer Head}${Search}${infer Tail}`
|
|
64
64
|
? Options['all'] extends true
|
|
65
|
-
?
|
|
65
|
+
? `${Head}${Replacement}${Replace<Tail, Search, Replacement, Options>}`
|
|
66
66
|
: `${Head}${Replacement}${Tail}`
|
|
67
67
|
: Input;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Extract all required keys from the given type.
|
|
3
|
+
|
|
4
|
+
This is useful when you want to create a new type that contains different type values for the required keys only or use the list of keys for validation purposes, etc...
|
|
5
|
+
|
|
6
|
+
@example
|
|
7
|
+
```
|
|
8
|
+
import type {RequiredKeysOf} from 'type-fest';
|
|
9
|
+
|
|
10
|
+
declare function createValidation<Entity extends object, Key extends RequiredKeysOf<Entity> = RequiredKeysOf<Entity>>(field: Key, validator: (value: Entity[Key]) => boolean): ValidatorFn;
|
|
11
|
+
|
|
12
|
+
interface User {
|
|
13
|
+
name: string;
|
|
14
|
+
surname: string;
|
|
15
|
+
|
|
16
|
+
luckyNumber?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const validator1 = createValidation<User>('name', value => value.length < 25);
|
|
20
|
+
const validator2 = createValidation<User>('surname', value => value.length < 25);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
@category Utilities
|
|
24
|
+
*/
|
|
25
|
+
export type RequiredKeysOf<BaseType extends object> = Exclude<{
|
|
26
|
+
[Key in keyof BaseType]: BaseType extends Record<Key, BaseType[Key]>
|
|
27
|
+
? Key
|
|
28
|
+
: never
|
|
29
|
+
}[keyof BaseType], undefined>;
|
package/source/simplify.d.ts
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@see Simplify
|
|
3
|
+
*/
|
|
4
|
+
export interface SimplifyOptions {
|
|
5
|
+
/**
|
|
6
|
+
Do the simplification recursively.
|
|
7
|
+
|
|
8
|
+
@default false
|
|
9
|
+
*/
|
|
10
|
+
deep?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Flatten a type without worrying about the result.
|
|
14
|
+
type Flatten<
|
|
15
|
+
AnyType,
|
|
16
|
+
Options extends SimplifyOptions = {},
|
|
17
|
+
> = Options['deep'] extends true
|
|
18
|
+
? {[KeyType in keyof AnyType]: Simplify<AnyType[KeyType], Options>}
|
|
19
|
+
: {[KeyType in keyof AnyType]: AnyType[KeyType]};
|
|
20
|
+
|
|
1
21
|
/**
|
|
2
22
|
Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
|
|
3
23
|
|
|
@@ -55,4 +75,9 @@ fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface`
|
|
|
55
75
|
|
|
56
76
|
@category Object
|
|
57
77
|
*/
|
|
58
|
-
export type Simplify<
|
|
78
|
+
export type Simplify<
|
|
79
|
+
AnyType,
|
|
80
|
+
Options extends SimplifyOptions = {},
|
|
81
|
+
> = Flatten<AnyType> extends AnyType
|
|
82
|
+
? Flatten<AnyType, Options>
|
|
83
|
+
: AnyType;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type {Except} from './except';
|
|
2
|
+
import type {RequiredKeysOf} from './required-keys-of';
|
|
3
|
+
import type {Simplify} from './simplify';
|
|
4
|
+
|
|
5
|
+
type Spread_<FirstType extends object, SecondType extends object> = {
|
|
6
|
+
[Key in keyof FirstType]: Key extends keyof SecondType
|
|
7
|
+
? FirstType[Key] | Required<SecondType>[Key]
|
|
8
|
+
: FirstType[Key];
|
|
9
|
+
} & Pick<
|
|
10
|
+
SecondType,
|
|
11
|
+
RequiredKeysOf<SecondType> | Exclude<keyof SecondType, keyof FirstType>
|
|
12
|
+
>;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
Mimic the type inferred by TypeScript when merging two objects using the spread operator.
|
|
16
|
+
|
|
17
|
+
@example
|
|
18
|
+
```
|
|
19
|
+
import type {Spread} from 'type-fest';
|
|
20
|
+
|
|
21
|
+
type Foo = {
|
|
22
|
+
a: number;
|
|
23
|
+
b?: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type Bar = {
|
|
27
|
+
b?: number;
|
|
28
|
+
c: boolean;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const foo = {a: 1, b: '2'};
|
|
32
|
+
const bar = {c: false};
|
|
33
|
+
const fooBar = {...foo, ...bar};
|
|
34
|
+
|
|
35
|
+
type FooBar = Spread<Foo, Bar>;
|
|
36
|
+
// type FooBar = {
|
|
37
|
+
// a: number;
|
|
38
|
+
// b?: string | number | undefined;
|
|
39
|
+
// c: boolean;
|
|
40
|
+
// }
|
|
41
|
+
|
|
42
|
+
const baz = (argument: FooBar) => {
|
|
43
|
+
// Do something
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
baz(fooBar);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
@category Object
|
|
50
|
+
*/
|
|
51
|
+
export type Spread<
|
|
52
|
+
FirstType extends object,
|
|
53
|
+
SecondType extends object,
|
|
54
|
+
> = Simplify<Spread_<FirstType, SecondType>>;
|
package/source/utilities.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export type UpperCaseCharacters = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';
|
|
2
|
-
|
|
3
|
-
export type WordSeparators = '-' | '_' | ' ';
|
|
4
|
-
|
|
5
|
-
export type StringDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
|