type-fest 2.14.0 → 2.16.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 +5 -1
- package/package.json +1 -1
- package/readme.md +4 -0
- 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/jsonify.d.ts +17 -12
- package/source/numeric.d.ts +2 -0
- package/source/optional-keys-of.d.ts +38 -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/index.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export {Entry} from './source/entry';
|
|
|
38
38
|
export {Entries} from './source/entries';
|
|
39
39
|
export {SetReturnType} from './source/set-return-type';
|
|
40
40
|
export {Asyncify} from './source/asyncify';
|
|
41
|
-
export {Simplify} from './source/simplify';
|
|
41
|
+
export {Simplify, SimplifyOptions} from './source/simplify';
|
|
42
42
|
export {Jsonify} from './source/jsonify';
|
|
43
43
|
export {Schema} from './source/schema';
|
|
44
44
|
export {LiteralToPrimitive} from './source/literal-to-primitive';
|
|
@@ -57,6 +57,10 @@ export {
|
|
|
57
57
|
export {StringKeyOf} from './source/string-key-of';
|
|
58
58
|
export {Exact} from './source/exact';
|
|
59
59
|
export {ReadonlyTuple} from './source/readonly-tuple';
|
|
60
|
+
export {OptionalKeysOf} from './source/optional-keys-of';
|
|
61
|
+
export {HasOptionalKeys} from './source/has-optional-keys';
|
|
62
|
+
export {RequiredKeysOf} from './source/required-keys-of';
|
|
63
|
+
export {HasRequiredKeys} from './source/has-required-keys';
|
|
60
64
|
|
|
61
65
|
// Template literal types
|
|
62
66
|
export {CamelCase} from './source/camel-case';
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -192,6 +192,10 @@ Click the type names for complete docs.
|
|
|
192
192
|
- [`StringKeyOf`](source/string-key-of.d.ts) - Get keys of the given type as strings.
|
|
193
193
|
- [`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
194
|
- [`Exact`](source/exact.d.ts) - Create a type that does not allow extra properties.
|
|
195
|
+
- [`OptionalKeysOf`](source/optional-keys-of.d.ts) - Extract all optional keys from the given type.
|
|
196
|
+
- [`HasOptionalKeys`](source/has-optional-keys.d.ts) - Create a `true`/`false` type depending on whether the given type has any optional fields.
|
|
197
|
+
- [`RequiredKeysOf`](source/required-keys-of.d.ts) - Extract all required keys from the given type.
|
|
198
|
+
- [`HasRequiredKeys`](source/has-required-keys.d.ts) - Create a `true`/`false` type depending on whether the given type has any required fields.
|
|
195
199
|
|
|
196
200
|
### JSON
|
|
197
201
|
|
|
@@ -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/jsonify.d.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import type {JsonPrimitive, JsonValue} from './basic';
|
|
2
|
+
import {Finite, NegativeInfinity, PositiveInfinity} from './numeric';
|
|
3
|
+
import {TypedArray} from './typed-array';
|
|
2
4
|
|
|
3
5
|
// Note: The return value has to be `any` and not `unknown` so it can match `void`.
|
|
4
|
-
type NotJsonable = ((...args: any[]) => any) | undefined;
|
|
5
|
-
|
|
6
|
-
// Note: Handles special case where Arrays with `undefined` are transformed to `'null'` by `JSON.stringify()`
|
|
7
|
-
// Only use with array members
|
|
8
|
-
type JsonifyArrayMember<T> =
|
|
9
|
-
T extends undefined ?
|
|
10
|
-
null | Exclude<T, undefined> :
|
|
11
|
-
Jsonify<T>;
|
|
6
|
+
type NotJsonable = ((...args: any[]) => any) | undefined | symbol;
|
|
12
7
|
|
|
13
8
|
/**
|
|
14
9
|
Transform a type to one that is assignable to the `JsonValue` type.
|
|
@@ -71,16 +66,26 @@ type Jsonify<T> =
|
|
|
71
66
|
// Check if there are any non-JSONable types represented in the union.
|
|
72
67
|
// Note: The use of tuples in this first condition side-steps distributive conditional types
|
|
73
68
|
// (see https://github.com/microsoft/TypeScript/issues/29368#issuecomment-453529532)
|
|
74
|
-
[Extract<T, NotJsonable>] extends [never]
|
|
75
|
-
? T extends
|
|
69
|
+
[Extract<T, NotJsonable | bigint>] extends [never]
|
|
70
|
+
? T extends PositiveInfinity | NegativeInfinity ? null
|
|
71
|
+
: T extends JsonPrimitive
|
|
76
72
|
? T // Primitive is acceptable
|
|
73
|
+
: T extends Number ? number
|
|
74
|
+
: T extends String ? string
|
|
75
|
+
: T extends Boolean ? boolean
|
|
76
|
+
: T extends Map<any, any> | Set<any> ? {}
|
|
77
|
+
: T extends TypedArray ? Record<string, number>
|
|
77
78
|
: T extends Array<infer U>
|
|
78
|
-
? Array<
|
|
79
|
+
? Array<Jsonify<U extends NotJsonable ? null : U>> // It's an array: recursive call for its children
|
|
79
80
|
: T extends object
|
|
80
81
|
? T extends {toJSON(): infer J}
|
|
81
82
|
? (() => J) extends (() => JsonValue) // Is J assignable to JsonValue?
|
|
82
83
|
? J // Then T is Jsonable and its Jsonable value is J
|
|
83
84
|
: never // Not Jsonable because its toJSON() method does not return JsonValue
|
|
84
|
-
: {[P in keyof T
|
|
85
|
+
: {[P in keyof T as P extends symbol
|
|
86
|
+
? never
|
|
87
|
+
: T[P] extends NotJsonable
|
|
88
|
+
? never
|
|
89
|
+
: P]: Jsonify<Required<T>[P]>} // It's an object: recursive call for its children
|
|
85
90
|
: never // Otherwise any other non-object is removed
|
|
86
91
|
: never; // Otherwise non-JSONable type union was found not empty
|
package/source/numeric.d.ts
CHANGED
|
@@ -34,6 +34,8 @@ You can't pass a `bigint` as they are already guaranteed to be finite.
|
|
|
34
34
|
|
|
35
35
|
Use-case: Validating and documenting parameters.
|
|
36
36
|
|
|
37
|
+
Note: This can't detect `NaN`, please upvote [this issue](https://github.com/microsoft/TypeScript/issues/28682) if you want to have this type as a built-in in TypeScript.
|
|
38
|
+
|
|
37
39
|
@example
|
|
38
40
|
```
|
|
39
41
|
import type {Finite} from 'type-fest';
|
|
@@ -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/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;
|