type-fest 4.7.0 → 4.8.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/basic.d.ts +2 -2
- package/source/delimiter-cased-properties-deep.d.ts +32 -9
- package/source/internal.d.ts +18 -4
- package/source/jsonifiable.d.ts +1 -1
- package/source/partial-deep.d.ts +5 -5
- package/source/pascal-case.d.ts +4 -4
- package/source/pascal-cased-properties-deep.d.ts +5 -4
- package/source/pascal-cased-properties.d.ts +3 -2
- package/source/paths.d.ts +24 -20
- package/source/pick-deep.d.ts +31 -23
package/package.json
CHANGED
package/source/basic.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ Matches a [`class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe
|
|
|
4
4
|
@category Class
|
|
5
5
|
*/
|
|
6
6
|
export type Class<T, Arguments extends unknown[] = any[]> = {
|
|
7
|
-
prototype: T
|
|
7
|
+
prototype: Pick<T, keyof T>;
|
|
8
8
|
new(...arguments_: Arguments): T;
|
|
9
9
|
};
|
|
10
10
|
|
|
@@ -25,7 +25,7 @@ We cannot use a `type` here because TypeScript throws: 'abstract' modifier canno
|
|
|
25
25
|
*/
|
|
26
26
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
27
27
|
export interface AbstractClass<T, Arguments extends unknown[] = any[]> extends AbstractConstructor<T, Arguments> {
|
|
28
|
-
prototype: T
|
|
28
|
+
prototype: Pick<T, keyof T>;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {DelimiterCase} from './delimiter-case';
|
|
2
|
+
import type {UnknownArray} from './unknown-array';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
Convert object properties to delimiter case recursively.
|
|
@@ -49,12 +50,34 @@ export type DelimiterCasedPropertiesDeep<
|
|
|
49
50
|
Delimiter extends string,
|
|
50
51
|
> = Value extends Function | Date | RegExp
|
|
51
52
|
? Value
|
|
52
|
-
: Value extends
|
|
53
|
-
?
|
|
54
|
-
: Value extends
|
|
55
|
-
?
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
: Value extends string
|
|
54
|
+
? DelimiterCase<Value, Delimiter>
|
|
55
|
+
: Value extends UnknownArray
|
|
56
|
+
? DelimiterCasedPropertiesArrayDeep<Value, Delimiter>
|
|
57
|
+
: Value extends Set<infer U>
|
|
58
|
+
? Set<DelimiterCasedPropertiesDeep<U, Delimiter>> : {
|
|
59
|
+
[K in keyof Value as DelimiterCase<
|
|
60
|
+
K,
|
|
61
|
+
Delimiter
|
|
62
|
+
>]: DelimiterCasedPropertiesDeep<Value[K], Delimiter>;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
type DelimiterCasedPropertiesArrayDeep<Value extends UnknownArray, Delimiter extends string> =
|
|
66
|
+
Value extends []
|
|
67
|
+
? []
|
|
68
|
+
// Tailing spread array
|
|
69
|
+
: Value extends [infer U, ...infer V]
|
|
70
|
+
? [DelimiterCasedPropertiesDeep<U, Delimiter>, ...DelimiterCasedPropertiesDeep<V, Delimiter>]
|
|
71
|
+
: Value extends readonly [infer U, ...infer V]
|
|
72
|
+
? readonly [DelimiterCasedPropertiesDeep<U, Delimiter>, ...DelimiterCasedPropertiesDeep<V, Delimiter>]
|
|
73
|
+
// Leading spread array
|
|
74
|
+
: Value extends readonly [...infer U, infer V]
|
|
75
|
+
? [...DelimiterCasedPropertiesDeep<U, Delimiter>, DelimiterCasedPropertiesDeep<V, Delimiter>]
|
|
76
|
+
: Value extends readonly [...infer U, infer V]
|
|
77
|
+
? readonly [...DelimiterCasedPropertiesDeep<U, Delimiter>, DelimiterCasedPropertiesDeep<V, Delimiter>]
|
|
78
|
+
// Array
|
|
79
|
+
: Value extends Array<infer U>
|
|
80
|
+
? Array<DelimiterCasedPropertiesDeep<U, Delimiter>>
|
|
81
|
+
: Value extends ReadonlyArray<infer U>
|
|
82
|
+
? ReadonlyArray<DelimiterCasedPropertiesDeep<U, Delimiter>>
|
|
83
|
+
: never;
|
package/source/internal.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ type B = BuildObject<'a', string, {readonly a?: any}>;
|
|
|
40
40
|
//=> {readonly a?: string}
|
|
41
41
|
```
|
|
42
42
|
*/
|
|
43
|
-
export type BuildObject<Key extends PropertyKey, Value, CopiedFrom extends
|
|
43
|
+
export type BuildObject<Key extends PropertyKey, Value, CopiedFrom extends object = {}> =
|
|
44
44
|
Key extends keyof CopiedFrom
|
|
45
45
|
? Pick<{[_ in keyof CopiedFrom]: Value}, Key>
|
|
46
46
|
: Key extends `${infer NumberKey extends number}`
|
|
@@ -67,9 +67,14 @@ export type Subtract<A extends number, B extends number> = BuildTuple<A> extends
|
|
|
67
67
|
: never;
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
|
-
Matches any primitive, `Date`,
|
|
70
|
+
Matches any primitive, `Date`, `RegExp`, `Element` value.
|
|
71
71
|
*/
|
|
72
|
-
export type BuiltIns = Primitive | Date | RegExp;
|
|
72
|
+
export type BuiltIns = Primitive | Date | RegExp | Element;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
Matches non-recursive types.
|
|
76
|
+
*/
|
|
77
|
+
export type NonRecursiveType = BuiltIns | Function | (new (...args: any[]) => unknown);
|
|
73
78
|
|
|
74
79
|
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';
|
|
75
80
|
|
|
@@ -150,7 +155,16 @@ Extract the object field type if T is an object and K is a key of T, return `nev
|
|
|
150
155
|
|
|
151
156
|
It creates a type-safe way to access the member type of `unknown` type.
|
|
152
157
|
*/
|
|
153
|
-
export type ObjectValue<T, K> =
|
|
158
|
+
export type ObjectValue<T, K> =
|
|
159
|
+
K extends keyof T
|
|
160
|
+
? T[K]
|
|
161
|
+
: ToString<K> extends keyof T
|
|
162
|
+
? T[ToString<K>]
|
|
163
|
+
: K extends `${infer NumberK extends number}`
|
|
164
|
+
? NumberK extends keyof T
|
|
165
|
+
? T[NumberK]
|
|
166
|
+
: never
|
|
167
|
+
: never;
|
|
154
168
|
|
|
155
169
|
/**
|
|
156
170
|
Returns a boolean for whether the string is lowercased.
|
package/source/jsonifiable.d.ts
CHANGED
package/source/partial-deep.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {BuiltIns
|
|
1
|
+
import type {BuiltIns} from './internal';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
@see PartialDeep
|
|
@@ -69,9 +69,8 @@ export type PartialDeep<T, Options extends PartialDeepOptions = {}> = T extends
|
|
|
69
69
|
? PartialReadonlyMapDeep<KeyType, ValueType, Options>
|
|
70
70
|
: T extends ReadonlySet<infer ItemType>
|
|
71
71
|
? PartialReadonlySetDeep<ItemType, Options>
|
|
72
|
-
: T extends
|
|
73
|
-
?
|
|
74
|
-
: T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
|
|
72
|
+
: T extends object
|
|
73
|
+
? T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
|
|
75
74
|
? Options['recurseIntoArrays'] extends true
|
|
76
75
|
? ItemType[] extends T // Test for arrays (non-tuples) specifically
|
|
77
76
|
? readonly ItemType[] extends T // Differentiate readonly and mutable arrays
|
|
@@ -79,7 +78,8 @@ export type PartialDeep<T, Options extends PartialDeepOptions = {}> = T extends
|
|
|
79
78
|
: Array<PartialDeep<ItemType | undefined, Options>>
|
|
80
79
|
: PartialObjectDeep<T, Options> // Tuples behave properly
|
|
81
80
|
: T // If they don't opt into array testing, just use the original type
|
|
82
|
-
: T
|
|
81
|
+
: PartialObjectDeep<T, Options>
|
|
82
|
+
: unknown;
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
85
|
Same as `PartialDeep`, but accepts only `Map`s and as inputs. Internal helper for `PartialDeep`.
|
package/source/pascal-case.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {CamelCase} from './camel-case';
|
|
1
|
+
import type {CamelCase, CamelCaseOptions} from './camel-case';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
Converts a string literal to pascal-case.
|
|
@@ -33,6 +33,6 @@ const dbResult: CamelCasedProperties<ModelProps> = {
|
|
|
33
33
|
@category Change case
|
|
34
34
|
@category Template literal
|
|
35
35
|
*/
|
|
36
|
-
export type PascalCase<Value> = CamelCase<Value> extends string
|
|
37
|
-
? Capitalize<CamelCase<Value>>
|
|
38
|
-
: CamelCase<Value>;
|
|
36
|
+
export type PascalCase<Value, Options extends CamelCaseOptions = {preserveConsecutiveUppercase: true}> = CamelCase<Value, Options> extends string
|
|
37
|
+
? Capitalize<CamelCase<Value, Options>>
|
|
38
|
+
: CamelCase<Value, Options>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type {CamelCaseOptions} from './camel-case';
|
|
1
2
|
import type {PascalCase} from './pascal-case';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -44,11 +45,11 @@ const result: PascalCasedPropertiesDeep<UserWithFriends> = {
|
|
|
44
45
|
@category Template literal
|
|
45
46
|
@category Object
|
|
46
47
|
*/
|
|
47
|
-
export type PascalCasedPropertiesDeep<Value> = Value extends Function | Date | RegExp
|
|
48
|
+
export type PascalCasedPropertiesDeep<Value, Options extends CamelCaseOptions = {preserveConsecutiveUppercase: true}> = Value extends Function | Date | RegExp
|
|
48
49
|
? Value
|
|
49
50
|
: Value extends Array<infer U>
|
|
50
|
-
? Array<PascalCasedPropertiesDeep<U>>
|
|
51
|
+
? Array<PascalCasedPropertiesDeep<U, Options>>
|
|
51
52
|
: Value extends Set<infer U>
|
|
52
|
-
? Set<PascalCasedPropertiesDeep<U>> : {
|
|
53
|
-
[K in keyof Value as PascalCase<K>]: PascalCasedPropertiesDeep<Value[K]>;
|
|
53
|
+
? Set<PascalCasedPropertiesDeep<U, Options>> : {
|
|
54
|
+
[K in keyof Value as PascalCase<K, Options>]: PascalCasedPropertiesDeep<Value[K], Options>;
|
|
54
55
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type {CamelCaseOptions} from './camel-case';
|
|
1
2
|
import type {PascalCase} from './pascal-case';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -27,8 +28,8 @@ const result: PascalCasedProperties<User> = {
|
|
|
27
28
|
@category Template literal
|
|
28
29
|
@category Object
|
|
29
30
|
*/
|
|
30
|
-
export type PascalCasedProperties<Value> = Value extends Function
|
|
31
|
+
export type PascalCasedProperties<Value, Options extends CamelCaseOptions = {preserveConsecutiveUppercase: true}> = Value extends Function
|
|
31
32
|
? Value
|
|
32
33
|
: Value extends Array<infer U>
|
|
33
34
|
? Value
|
|
34
|
-
: {[K in keyof Value as PascalCase<K>]: Value[K]};
|
|
35
|
+
: {[K in keyof Value as PascalCase<K, Options>]: Value[K]};
|
package/source/paths.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type {ToString} from './internal';
|
|
1
|
+
import type {NonRecursiveType, ToString} from './internal';
|
|
2
2
|
import type {EmptyObject} from './empty-object';
|
|
3
3
|
import type {IsAny} from './is-any';
|
|
4
4
|
import type {IsNever} from './is-never';
|
|
5
5
|
import type {UnknownArray} from './unknown-array';
|
|
6
|
-
import type {UnknownRecord} from './unknown-record';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
Return the part of the given array with a fixed index.
|
|
@@ -78,30 +77,35 @@ open('listB.1'); // TypeError. Because listB only has one element.
|
|
|
78
77
|
@category Object
|
|
79
78
|
@category Array
|
|
80
79
|
*/
|
|
81
|
-
export type Paths<T
|
|
82
|
-
|
|
80
|
+
export type Paths<T> =
|
|
81
|
+
T extends NonRecursiveType
|
|
83
82
|
? never
|
|
84
|
-
: T extends
|
|
85
|
-
?
|
|
86
|
-
|
|
87
|
-
?
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
: IsAny<T> extends true
|
|
84
|
+
? never
|
|
85
|
+
: T extends UnknownArray
|
|
86
|
+
? number extends T['length']
|
|
87
|
+
// We need to handle the fixed and non-fixed index part of the array separately.
|
|
88
|
+
? InternalPaths<FilterFixedIndexArray<T>>
|
|
89
|
+
| InternalPaths<Array<FilterNotFixedIndexArray<T>[number]>>
|
|
90
|
+
: InternalPaths<T>
|
|
91
|
+
: T extends object
|
|
92
|
+
? InternalPaths<T>
|
|
93
|
+
: never;
|
|
91
94
|
|
|
92
|
-
export type InternalPaths<_T
|
|
95
|
+
export type InternalPaths<_T, T = Required<_T>> =
|
|
93
96
|
T extends EmptyObject | readonly []
|
|
94
97
|
? never
|
|
95
98
|
: {
|
|
96
99
|
[Key in keyof T]:
|
|
97
100
|
Key extends string | number // Limit `Key` to string or number.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
// If `Key` is a number, return `Key | `${Key}``, because both `array[0]` and `array['0']` work.
|
|
102
|
+
?
|
|
103
|
+
| Key
|
|
104
|
+
| ToString<Key>
|
|
105
|
+
| (
|
|
106
|
+
IsNever<Paths<T[Key]>> extends false
|
|
107
|
+
? `${Key}.${Paths<T[Key]>}`
|
|
108
|
+
: never
|
|
109
|
+
)
|
|
106
110
|
: never
|
|
107
111
|
}[keyof T & (T extends UnknownArray ? number : unknown)];
|
package/source/pick-deep.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {BuildObject, BuildTuple,
|
|
1
|
+
import type {BuildObject, BuildTuple, NonRecursiveType, ObjectValue} from './internal';
|
|
2
|
+
import type {IsNever} from './is-never';
|
|
2
3
|
import type {Paths} from './paths';
|
|
3
4
|
import type {Simplify} from './simplify.d';
|
|
4
5
|
import type {UnionToIntersection} from './union-to-intersection.d';
|
|
5
6
|
import type {UnknownArray} from './unknown-array';
|
|
6
|
-
import type {UnknownRecord} from './unknown-record.d';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
Pick properties from a deeply-nested object.
|
|
@@ -37,7 +37,8 @@ type Configuration = {
|
|
|
37
37
|
type NameConfig = PickDeep<Configuration, 'userConfig.name'>;
|
|
38
38
|
// type NameConfig = {
|
|
39
39
|
// userConfig: {
|
|
40
|
-
//
|
|
40
|
+
// name: string;
|
|
41
|
+
// }
|
|
41
42
|
// };
|
|
42
43
|
|
|
43
44
|
// Supports optional properties
|
|
@@ -50,7 +51,7 @@ type User = PickDeep<PartialDeep<Configuration>, 'userConfig.name' | 'userConfig
|
|
|
50
51
|
// };
|
|
51
52
|
|
|
52
53
|
// Supports array
|
|
53
|
-
type AddressConfig = PickDeep<Configuration,
|
|
54
|
+
type AddressConfig = PickDeep<Configuration, 'userConfig.address.0'>;
|
|
54
55
|
// type AddressConfig = {
|
|
55
56
|
// userConfig: {
|
|
56
57
|
// address: [{
|
|
@@ -61,8 +62,8 @@ type AddressConfig = PickDeep<Configuration, `userConfig.address.0`>;
|
|
|
61
62
|
// }
|
|
62
63
|
|
|
63
64
|
// Supports recurse into array
|
|
64
|
-
type Street = PickDeep<Configuration,
|
|
65
|
-
// type
|
|
65
|
+
type Street = PickDeep<Configuration, 'userConfig.address.1.street2'>;
|
|
66
|
+
// type Street = {
|
|
66
67
|
// userConfig: {
|
|
67
68
|
// address: [
|
|
68
69
|
// unknown,
|
|
@@ -75,37 +76,44 @@ type Street = PickDeep<Configuration, `userConfig.address.1.street2`>;
|
|
|
75
76
|
@category Object
|
|
76
77
|
@category Array
|
|
77
78
|
*/
|
|
78
|
-
export type PickDeep<T
|
|
79
|
-
T extends
|
|
80
|
-
?
|
|
81
|
-
[P in PathUnion]: InternalPickDeep<T, P>;
|
|
82
|
-
}[PathUnion]>>
|
|
79
|
+
export type PickDeep<T, PathUnion extends Paths<T>> =
|
|
80
|
+
T extends NonRecursiveType
|
|
81
|
+
? never
|
|
83
82
|
: T extends UnknownArray
|
|
84
83
|
? UnionToIntersection<{
|
|
85
84
|
[P in PathUnion]: InternalPickDeep<T, P>;
|
|
86
85
|
}[PathUnion]
|
|
87
86
|
>
|
|
88
|
-
:
|
|
87
|
+
: T extends object
|
|
88
|
+
? Simplify<UnionToIntersection<{
|
|
89
|
+
[P in PathUnion]: InternalPickDeep<T, P>;
|
|
90
|
+
}[PathUnion]>>
|
|
91
|
+
: never;
|
|
89
92
|
|
|
90
93
|
/**
|
|
91
94
|
Pick an object/array from the given object/array by one path.
|
|
92
95
|
*/
|
|
93
|
-
type InternalPickDeep<
|
|
94
|
-
T extends
|
|
95
|
-
|
|
96
|
-
>
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
: never;
|
|
96
|
+
type InternalPickDeep<T, Path extends string | number> =
|
|
97
|
+
T extends NonRecursiveType
|
|
98
|
+
? never
|
|
99
|
+
: T extends UnknownArray ? PickDeepArray<T, Path>
|
|
100
|
+
: T extends object ? Simplify<PickDeepObject<T, Path>>
|
|
101
|
+
: never;
|
|
100
102
|
|
|
101
103
|
/**
|
|
102
104
|
Pick an object from the given object by one path.
|
|
103
105
|
*/
|
|
104
|
-
type PickDeepObject<RecordType extends
|
|
106
|
+
type PickDeepObject<RecordType extends object, P extends string | number> =
|
|
105
107
|
P extends `${infer RecordKeyInPath}.${infer SubPath}`
|
|
106
|
-
?
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
? ObjectValue<RecordType, RecordKeyInPath> extends infer ObjectV
|
|
109
|
+
? IsNever<ObjectV> extends false
|
|
110
|
+
? BuildObject<RecordKeyInPath, InternalPickDeep<NonNullable<ObjectV>, SubPath>, RecordType>
|
|
111
|
+
: never
|
|
112
|
+
: never
|
|
113
|
+
: ObjectValue<RecordType, P> extends infer ObjectV
|
|
114
|
+
? IsNever<ObjectV> extends false
|
|
115
|
+
? BuildObject<P, ObjectV, RecordType>
|
|
116
|
+
: never
|
|
109
117
|
: never;
|
|
110
118
|
|
|
111
119
|
/**
|