type-fest 5.2.0 → 5.3.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 +5 -2
- package/source/all-union-fields.d.ts +8 -7
- package/source/array-slice.d.ts +29 -8
- package/source/array-splice.d.ts +8 -6
- package/source/arrayable.d.ts +1 -1
- package/source/async-return-type.d.ts +6 -3
- package/source/asyncify.d.ts +7 -16
- package/source/camel-case.d.ts +3 -3
- package/source/camel-cased-properties-deep.d.ts +4 -4
- package/source/camel-cased-properties.d.ts +2 -2
- package/source/characters.d.ts +8 -3
- package/source/conditional-except.d.ts +6 -6
- package/source/conditional-pick-deep.d.ts +2 -2
- package/source/conditional-pick.d.ts +6 -6
- package/source/delimiter-case.d.ts +3 -3
- package/source/delimiter-cased-properties-deep.d.ts +6 -6
- package/source/delimiter-cased-properties.d.ts +2 -2
- package/source/distributed-omit.d.ts +15 -10
- package/source/distributed-pick.d.ts +12 -7
- package/source/empty-object.d.ts +7 -4
- package/source/entries.d.ts +3 -3
- package/source/entry.d.ts +3 -3
- package/source/exact.d.ts +5 -3
- package/source/except.d.ts +5 -3
- package/source/exclude-rest-element.d.ts +1 -1
- package/source/exclude-strict.d.ts +4 -0
- package/source/extract-rest-element.d.ts +1 -1
- package/source/extract-strict.d.ts +4 -0
- package/source/find-global-type.d.ts +7 -5
- package/source/fixed-length-array.d.ts +8 -0
- package/source/get.d.ts +27 -28
- package/source/global-this.d.ts +2 -1
- package/source/greater-than-or-equal.d.ts +3 -3
- package/source/greater-than.d.ts +3 -3
- package/source/has-optional-keys.d.ts +2 -2
- package/source/has-readonly-keys.d.ts +2 -2
- package/source/has-required-keys.d.ts +10 -10
- package/source/has-writable-keys.d.ts +2 -2
- package/source/if.d.ts +3 -3
- package/source/int-closed-range.d.ts +17 -7
- package/source/int-range.d.ts +17 -7
- package/source/internal/array.d.ts +4 -4
- package/source/internal/numeric.d.ts +7 -7
- package/source/internal/object.d.ts +13 -12
- package/source/internal/string.d.ts +15 -15
- package/source/internal/tuple.d.ts +5 -5
- package/source/internal/type.d.ts +6 -6
- package/source/invariant-of.d.ts +26 -19
- package/source/is-any.d.ts +2 -2
- package/source/is-equal.d.ts +4 -8
- package/source/is-integer.d.ts +1 -1
- package/source/is-literal.d.ts +13 -13
- package/source/is-lowercase.d.ts +3 -3
- package/source/is-never.d.ts +35 -23
- package/source/is-null.d.ts +1 -1
- package/source/is-optional-key-of.d.ts +4 -4
- package/source/is-readonly-key-of.d.ts +4 -4
- package/source/is-required-key-of.d.ts +4 -4
- package/source/is-unknown.d.ts +12 -23
- package/source/is-uppercase.d.ts +3 -3
- package/source/is-writable-key-of.d.ts +4 -4
- package/source/iterable-element.d.ts +3 -3
- package/source/join.d.ts +27 -18
- package/source/jsonifiable.d.ts +5 -5
- package/source/jsonify.d.ts +7 -8
- package/source/kebab-case.d.ts +3 -3
- package/source/kebab-cased-properties-deep.d.ts +6 -6
- package/source/kebab-cased-properties.d.ts +2 -2
- package/source/last-array-element.d.ts +5 -9
- package/source/less-than-or-equal.d.ts +3 -3
- package/source/less-than.d.ts +3 -3
- package/source/literal-to-primitive-deep.d.ts +40 -7
- package/source/literal-union.d.ts +2 -2
- package/source/merge-deep.d.ts +6 -8
- package/source/merge-exclusive.d.ts +7 -4
- package/source/merge.d.ts +2 -2
- package/source/multidimensional-array.d.ts +7 -15
- package/source/multidimensional-readonly-array.d.ts +7 -19
- package/source/non-empty-object.d.ts +1 -0
- package/source/non-empty-string.d.ts +3 -1
- package/source/non-empty-tuple.d.ts +1 -0
- package/source/numeric.d.ts +6 -4
- package/source/omit-deep.d.ts +13 -12
- package/source/omit-index-signature.d.ts +17 -20
- package/source/optional-keys-of.d.ts +4 -4
- package/source/override-properties.d.ts +11 -6
- package/source/package-json.d.ts +12 -0
- package/source/partial-on-undefined-deep.d.ts +2 -2
- package/source/pascal-case.d.ts +1 -1
- package/source/pascal-cased-properties-deep.d.ts +4 -4
- package/source/pascal-cased-properties.d.ts +2 -2
- package/source/paths.d.ts +12 -0
- package/source/pick-deep.d.ts +2 -2
- package/source/promisable.d.ts +2 -2
- package/source/readonly-deep.d.ts +45 -12
- package/source/readonly-keys-of.d.ts +3 -3
- package/source/readonly-tuple.d.ts +5 -3
- package/source/remove-prefix.d.ts +2 -0
- package/source/replace.d.ts +3 -3
- package/source/require-all-or-none.d.ts +2 -2
- package/source/require-at-least-one.d.ts +1 -1
- package/source/require-exactly-one.d.ts +1 -1
- package/source/require-one-or-none.d.ts +3 -3
- package/source/required-keys-of.d.ts +10 -4
- package/source/set-field-type.d.ts +2 -2
- package/source/set-non-nullable.d.ts +1 -1
- package/source/set-optional.d.ts +1 -1
- package/source/set-parameter-type.d.ts +12 -6
- package/source/set-readonly.d.ts +1 -1
- package/source/set-required-deep.d.ts +4 -4
- package/source/set-required.d.ts +1 -1
- package/source/set-return-type.d.ts +3 -3
- package/source/shared-union-fields-deep.d.ts +5 -5
- package/source/shared-union-fields.d.ts +5 -5
- package/source/simplify-deep.d.ts +2 -3
- package/source/simplify.d.ts +2 -1
- package/source/single-key-object.d.ts +4 -8
- package/source/snake-case.d.ts +3 -3
- package/source/snake-cased-properties-deep.d.ts +5 -5
- package/source/snake-cased-properties.d.ts +2 -2
- package/source/split.d.ts +4 -4
- package/source/spread.d.ts +2 -6
- package/source/string-repeat.d.ts +2 -2
- package/source/string-slice.d.ts +6 -6
- package/source/stringified.d.ts +2 -2
- package/source/structured-cloneable.d.ts +11 -16
- package/source/subtract.d.ts +7 -7
- package/source/sum.d.ts +6 -6
- package/source/tagged-union.d.ts +2 -2
- package/source/tagged.d.ts +15 -13
- package/source/trim.d.ts +1 -1
- package/source/tuple-of.d.ts +2 -0
- package/source/tuple-to-object.d.ts +2 -0
- package/source/tuple-to-union.d.ts +3 -2
- package/source/undefined-on-partial-deep.d.ts +5 -4
- package/source/union-to-intersection.d.ts +0 -28
- package/source/union-to-tuple.d.ts +3 -3
- package/source/value-of.d.ts +6 -26
- package/source/words.d.ts +2 -0
- package/source/writable-keys-of.d.ts +2 -2
- package/source/writable.d.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "type-fest",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.0",
|
|
4
4
|
"description": "A collection of essential TypeScript types",
|
|
5
5
|
"license": "(MIT OR CC0-1.0)",
|
|
6
6
|
"repository": "sindresorhus/type-fest",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"node": ">=20"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
|
-
"test:tsc": "tsc",
|
|
28
|
+
"test:tsc": "node --max-old-space-size=5120 ./node_modules/.bin/tsc",
|
|
29
29
|
"test:tsd": "tsd",
|
|
30
30
|
"test:xo": "xo",
|
|
31
31
|
"test:linter": "node --test",
|
|
@@ -56,10 +56,13 @@
|
|
|
56
56
|
"@sindresorhus/tsconfig": "^8.0.1",
|
|
57
57
|
"@typescript-eslint/parser": "^8.44.0",
|
|
58
58
|
"eslint": "^9.35.0",
|
|
59
|
+
"@typescript/vfs": "^1.6.1",
|
|
60
|
+
"dedent": "^1.7.0",
|
|
59
61
|
"expect-type": "^1.2.2",
|
|
60
62
|
"npm-run-all2": "^8.0.4",
|
|
61
63
|
"tsd": "^0.33.0",
|
|
62
64
|
"typescript": "^5.9.2",
|
|
65
|
+
"typescript-eslint": "^8.47.0",
|
|
63
66
|
"xo": "^1.2.2"
|
|
64
67
|
},
|
|
65
68
|
"tsd": {
|
|
@@ -38,14 +38,15 @@ function displayPetInfo(petInfo: Cat | Dog) {
|
|
|
38
38
|
// dogType: string;
|
|
39
39
|
// }
|
|
40
40
|
|
|
41
|
-
console.log('name:
|
|
42
|
-
console.log('type:
|
|
41
|
+
console.log('name:', petInfo.name);
|
|
42
|
+
console.log('type:', petInfo.type);
|
|
43
43
|
|
|
44
44
|
// TypeScript complains about `catType` and `dogType` not existing on type `Cat | Dog`.
|
|
45
|
-
|
|
45
|
+
// @ts-expect-error
|
|
46
|
+
console.log('animal type:', petInfo.catType ?? petInfo.dogType);
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
function
|
|
49
|
+
function displayPetInfoWithAllUnionFields(petInfo: AllUnionFields<Cat | Dog>) {
|
|
49
50
|
// typeof petInfo =>
|
|
50
51
|
// {
|
|
51
52
|
// name: string;
|
|
@@ -54,11 +55,11 @@ function displayPetInfo(petInfo: AllUnionFields<Cat | Dog>) {
|
|
|
54
55
|
// dogType?: string;
|
|
55
56
|
// }
|
|
56
57
|
|
|
57
|
-
console.log('name:
|
|
58
|
-
console.log('type:
|
|
58
|
+
console.log('name:', petInfo.name);
|
|
59
|
+
console.log('type:', petInfo.type);
|
|
59
60
|
|
|
60
61
|
// No TypeScript error.
|
|
61
|
-
console.log('animal type:
|
|
62
|
+
console.log('animal type:', petInfo.catType ?? petInfo.dogType);
|
|
62
63
|
}
|
|
63
64
|
```
|
|
64
65
|
|
package/source/array-slice.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type {Not, TupleMin} from './internal/index.d.ts';
|
|
|
7
7
|
import type {IsEqual} from './is-equal.d.ts';
|
|
8
8
|
import type {And} from './and.d.ts';
|
|
9
9
|
import type {ArraySplice} from './array-splice.d.ts';
|
|
10
|
+
import type {IsNever} from './is-never.d.ts';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
Returns an array slice of a given range, just like `Array#slice()`.
|
|
@@ -43,14 +44,14 @@ function arraySlice<
|
|
|
43
44
|
|
|
44
45
|
const slice = arraySlice([1, '2', {a: 3}, [4, 5]], 0, -1);
|
|
45
46
|
|
|
46
|
-
typeof slice;
|
|
47
|
+
type Slice = typeof slice;
|
|
47
48
|
//=> [1, '2', { readonly a: 3; }]
|
|
48
49
|
|
|
49
|
-
slice[2].a;
|
|
50
|
+
const value = slice[2].a;
|
|
50
51
|
//=> 3
|
|
51
52
|
|
|
52
53
|
// @ts-expect-error -- TS2493: Tuple type '[1, "2", {readonly a: 3}]' of length '3' has no element at index '3'.
|
|
53
|
-
slice[3];
|
|
54
|
+
const invalidIndexAccess = slice[3];
|
|
54
55
|
```
|
|
55
56
|
|
|
56
57
|
@category Array
|
|
@@ -60,13 +61,33 @@ export type ArraySlice<
|
|
|
60
61
|
Start extends number = never,
|
|
61
62
|
End extends number = never,
|
|
62
63
|
> = Array_ extends unknown // To distributive type
|
|
63
|
-
?
|
|
64
|
-
?
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
? IsNever<Start> extends true
|
|
65
|
+
? IsNever<End> extends true
|
|
66
|
+
? _ArraySlice<Array_, Start, End>
|
|
67
|
+
: End extends unknown // To distribute `End`
|
|
68
|
+
? _ArraySlice<Array_, Start, End>
|
|
69
|
+
: never // Never happens
|
|
70
|
+
: IsNever<End> extends true
|
|
71
|
+
? Start extends unknown // To distribute `Start`
|
|
72
|
+
? _ArraySlice<Array_, Start, End>
|
|
73
|
+
: never // Never happens
|
|
74
|
+
: Start extends unknown // To distribute `Start`
|
|
75
|
+
? End extends unknown // To distribute `End`
|
|
76
|
+
? _ArraySlice<Array_, Start, End>
|
|
77
|
+
: never // Never happens
|
|
78
|
+
: never // Never happens
|
|
68
79
|
: never; // Never happens
|
|
69
80
|
|
|
81
|
+
type _ArraySlice<
|
|
82
|
+
Array_ extends readonly unknown[],
|
|
83
|
+
Start extends number = 0,
|
|
84
|
+
End extends number = Array_['length'],
|
|
85
|
+
> = And<IsEqual<Start, never>, IsEqual<End, never>> extends true
|
|
86
|
+
? Array_
|
|
87
|
+
: number extends Array_['length']
|
|
88
|
+
? VariableLengthArraySliceHelper<Array_, Start, End>
|
|
89
|
+
: ArraySliceHelper<Array_, IsEqual<Start, never> extends true ? 0 : Start, IsEqual<End, never> extends true ? Array_['length'] : End>;
|
|
90
|
+
|
|
70
91
|
type VariableLengthArraySliceHelper<
|
|
71
92
|
Array_ extends readonly unknown[],
|
|
72
93
|
Start extends number,
|
package/source/array-splice.d.ts
CHANGED
|
@@ -72,17 +72,19 @@ Like [`Array#splice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/
|
|
|
72
72
|
|
|
73
73
|
@example
|
|
74
74
|
```
|
|
75
|
+
import type {ArraySplice} from 'type-fest';
|
|
76
|
+
|
|
75
77
|
type SomeMonths0 = ['January', 'April', 'June'];
|
|
76
|
-
type
|
|
77
|
-
//=>
|
|
78
|
+
type Months0 = ArraySplice<SomeMonths0, 1, 0, ['Feb', 'March']>;
|
|
79
|
+
//=> ['January', 'Feb', 'March', 'April', 'June'];
|
|
78
80
|
|
|
79
81
|
type SomeMonths1 = ['January', 'April', 'June'];
|
|
80
|
-
type
|
|
81
|
-
//=>
|
|
82
|
+
type Months1 = ArraySplice<SomeMonths1, 1, 1>;
|
|
83
|
+
//=> ['January', 'June'];
|
|
82
84
|
|
|
83
85
|
type SomeMonths2 = ['January', 'Foo', 'April'];
|
|
84
|
-
type
|
|
85
|
-
//=>
|
|
86
|
+
type Months2 = ArraySplice<SomeMonths2, 1, 1, ['Feb', 'March']>;
|
|
87
|
+
//=> ['January', 'Feb', 'March', 'April'];
|
|
86
88
|
```
|
|
87
89
|
|
|
88
90
|
@category Array
|
package/source/arrayable.d.ts
CHANGED
|
@@ -8,14 +8,17 @@ There has been [discussion](https://github.com/microsoft/TypeScript/pull/35998)
|
|
|
8
8
|
@example
|
|
9
9
|
```ts
|
|
10
10
|
import type {AsyncReturnType} from 'type-fest';
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
declare function asyncFunction(): Promise<{foo: string}>;
|
|
12
13
|
|
|
13
14
|
// This type resolves to the unwrapped return type of `asyncFunction`.
|
|
14
15
|
type Value = AsyncReturnType<typeof asyncFunction>;
|
|
16
|
+
//=> {foo: string}
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
declare function doSomething(value: Value): void;
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
const value = await asyncFunction();
|
|
21
|
+
doSomething(value);
|
|
19
22
|
```
|
|
20
23
|
|
|
21
24
|
@category Async
|
package/source/asyncify.d.ts
CHANGED
|
@@ -9,22 +9,13 @@ Use-case: You have two functions, one synchronous and one asynchronous that do t
|
|
|
9
9
|
```
|
|
10
10
|
import type {Asyncify} from 'type-fest';
|
|
11
11
|
|
|
12
|
-
// Synchronous function
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
type
|
|
18
|
-
//=>
|
|
19
|
-
|
|
20
|
-
// Same as `getFooSync` but asynchronous.
|
|
21
|
-
const getFooAsync: AsyncifiedFooGetter = (someArg) => {
|
|
22
|
-
// TypeScript now knows that `someArg` is `SomeType` automatically.
|
|
23
|
-
// It also knows that this function must return `Promise<Foo>`.
|
|
24
|
-
// If you have `@typescript-eslint/promise-function-async` linter rule enabled, it will even report that "Functions that return promises must be async.".
|
|
25
|
-
|
|
26
|
-
// …
|
|
27
|
-
}
|
|
12
|
+
// Synchronous function
|
|
13
|
+
type Config = {featureFlags: Record<string, boolean>};
|
|
14
|
+
|
|
15
|
+
declare function loadConfigSync(path: string): Config;
|
|
16
|
+
|
|
17
|
+
type LoadConfigAsync = Asyncify<typeof loadConfigSync>;
|
|
18
|
+
//=> (path: string) => Promise<Config>
|
|
28
19
|
```
|
|
29
20
|
|
|
30
21
|
@category Async
|
package/source/camel-case.d.ts
CHANGED
|
@@ -58,14 +58,14 @@ type CamelCasedProperties<T> = {
|
|
|
58
58
|
[K in keyof T as CamelCase<K>]: T[K]
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
type RawOptions = {
|
|
62
62
|
'dry-run': boolean;
|
|
63
63
|
'full_family_name': string;
|
|
64
64
|
foo: number;
|
|
65
65
|
BAR: string;
|
|
66
66
|
QUZ_QUX: number;
|
|
67
67
|
'OTHER-FIELD': boolean;
|
|
68
|
-
}
|
|
68
|
+
};
|
|
69
69
|
|
|
70
70
|
const dbResult: CamelCasedProperties<RawOptions> = {
|
|
71
71
|
dryRun: true,
|
|
@@ -73,7 +73,7 @@ const dbResult: CamelCasedProperties<RawOptions> = {
|
|
|
73
73
|
foo: 123,
|
|
74
74
|
bar: 'foo',
|
|
75
75
|
quzQux: 6,
|
|
76
|
-
otherField: false
|
|
76
|
+
otherField: false,
|
|
77
77
|
};
|
|
78
78
|
```
|
|
79
79
|
|
|
@@ -14,15 +14,15 @@ This can be useful when, for example, converting some API types from a different
|
|
|
14
14
|
```
|
|
15
15
|
import type {CamelCasedPropertiesDeep} from 'type-fest';
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
type User = {
|
|
18
18
|
UserId: number;
|
|
19
19
|
UserName: string;
|
|
20
|
-
}
|
|
20
|
+
};
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
type UserWithFriends = {
|
|
23
23
|
UserInfo: User;
|
|
24
24
|
UserFriends: User[];
|
|
25
|
-
}
|
|
25
|
+
};
|
|
26
26
|
|
|
27
27
|
const result: CamelCasedPropertiesDeep<UserWithFriends> = {
|
|
28
28
|
userInfo: {
|
|
@@ -13,10 +13,10 @@ This can be useful when, for example, converting some API types from a different
|
|
|
13
13
|
```
|
|
14
14
|
import type {CamelCasedProperties} from 'type-fest';
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
type User = {
|
|
17
17
|
UserId: number;
|
|
18
18
|
UserName: string;
|
|
19
|
-
}
|
|
19
|
+
};
|
|
20
20
|
|
|
21
21
|
const result: CamelCasedProperties<User> = {
|
|
22
22
|
userId: 1,
|
package/source/characters.d.ts
CHANGED
|
@@ -5,8 +5,10 @@ Matches any uppercase letter in the basic Latin alphabet (A-Z).
|
|
|
5
5
|
```
|
|
6
6
|
import type {UppercaseLetter} from 'type-fest';
|
|
7
7
|
|
|
8
|
-
const a: UppercaseLetter = 'A';
|
|
9
|
-
|
|
8
|
+
const a: UppercaseLetter = 'A'; // Valid
|
|
9
|
+
// @ts-expect-error
|
|
10
|
+
const b: UppercaseLetter = 'a'; // Invalid
|
|
11
|
+
// @ts-expect-error
|
|
10
12
|
const c: UppercaseLetter = 'AB'; // Invalid
|
|
11
13
|
```
|
|
12
14
|
|
|
@@ -22,6 +24,7 @@ Matches any lowercase letter in the basic Latin alphabet (a-z).
|
|
|
22
24
|
import type {LowercaseLetter} from 'type-fest';
|
|
23
25
|
|
|
24
26
|
const a: LowercaseLetter = 'a'; // Valid
|
|
27
|
+
// @ts-expect-error
|
|
25
28
|
const b: LowercaseLetter = 'A'; // Invalid
|
|
26
29
|
```
|
|
27
30
|
|
|
@@ -37,7 +40,8 @@ Matches any digit as a string ('0'-'9').
|
|
|
37
40
|
import type {DigitCharacter} from 'type-fest';
|
|
38
41
|
|
|
39
42
|
const a: DigitCharacter = '0'; // Valid
|
|
40
|
-
|
|
43
|
+
// @ts-expect-error
|
|
44
|
+
const b: DigitCharacter = 0; // Invalid
|
|
41
45
|
```
|
|
42
46
|
|
|
43
47
|
@category Type
|
|
@@ -52,6 +56,7 @@ Matches any lowercase letter (a-z), uppercase letter (A-Z), or digit ('0'-'9') i
|
|
|
52
56
|
import type {Alphanumeric} from 'type-fest';
|
|
53
57
|
|
|
54
58
|
const a: Alphanumeric = 'A'; // Valid
|
|
59
|
+
// @ts-expect-error
|
|
55
60
|
const b: Alphanumeric = '#'; // Invalid
|
|
56
61
|
```
|
|
57
62
|
|
|
@@ -11,11 +11,11 @@ This is useful when you want to create a new type with a specific set of keys fr
|
|
|
11
11
|
import type {Primitive, ConditionalExcept} from 'type-fest';
|
|
12
12
|
|
|
13
13
|
class Awesome {
|
|
14
|
-
name: string
|
|
15
|
-
successes: number;
|
|
16
|
-
failures: bigint;
|
|
14
|
+
constructor(public name: string, public successes: number, public failures: bigint) {}
|
|
17
15
|
|
|
18
|
-
run() {
|
|
16
|
+
run() {
|
|
17
|
+
// do something
|
|
18
|
+
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
type ExceptPrimitivesFromAwesome = ConditionalExcept<Awesome, Primitive>;
|
|
@@ -26,12 +26,12 @@ type ExceptPrimitivesFromAwesome = ConditionalExcept<Awesome, Primitive>;
|
|
|
26
26
|
```
|
|
27
27
|
import type {ConditionalExcept} from 'type-fest';
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
type Example = {
|
|
30
30
|
a: string;
|
|
31
31
|
b: string | number;
|
|
32
32
|
c: () => void;
|
|
33
33
|
d: {};
|
|
34
|
-
}
|
|
34
|
+
};
|
|
35
35
|
|
|
36
36
|
type NonStringKeysOnly = ConditionalExcept<Example, string>;
|
|
37
37
|
//=> {b: string | number; c: () => void; d: {}}
|
|
@@ -46,7 +46,7 @@ Pick keys recursively from the shape that matches the given condition.
|
|
|
46
46
|
```
|
|
47
47
|
import type {ConditionalPickDeep} from 'type-fest';
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
type Example = {
|
|
50
50
|
a: string;
|
|
51
51
|
b: string | boolean;
|
|
52
52
|
c: {
|
|
@@ -59,7 +59,7 @@ interface Example {
|
|
|
59
59
|
};
|
|
60
60
|
j: boolean;
|
|
61
61
|
};
|
|
62
|
-
}
|
|
62
|
+
};
|
|
63
63
|
|
|
64
64
|
type StringPick = ConditionalPickDeep<Example, string>;
|
|
65
65
|
//=> {a: string; c: {d: string}}
|
|
@@ -10,11 +10,11 @@ This is useful when you want to create a new type from a specific subset of an e
|
|
|
10
10
|
import type {Primitive, ConditionalPick} from 'type-fest';
|
|
11
11
|
|
|
12
12
|
class Awesome {
|
|
13
|
-
name: string
|
|
14
|
-
successes: number;
|
|
15
|
-
failures: bigint;
|
|
13
|
+
constructor(public name: string, public successes: number, public failures: bigint) {}
|
|
16
14
|
|
|
17
|
-
run() {
|
|
15
|
+
run() {
|
|
16
|
+
// do something
|
|
17
|
+
}
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
type PickPrimitivesFromAwesome = ConditionalPick<Awesome, Primitive>;
|
|
@@ -25,12 +25,12 @@ type PickPrimitivesFromAwesome = ConditionalPick<Awesome, Primitive>;
|
|
|
25
25
|
```
|
|
26
26
|
import type {ConditionalPick} from 'type-fest';
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
type Example = {
|
|
29
29
|
a: string;
|
|
30
30
|
b: string | number;
|
|
31
31
|
c: () => void;
|
|
32
32
|
d: {};
|
|
33
|
-
}
|
|
33
|
+
};
|
|
34
34
|
|
|
35
35
|
type StringKeysOnly = ConditionalPick<Example, string>;
|
|
36
36
|
//=> {a: string}
|
|
@@ -45,16 +45,16 @@ type OddlyCasedProperties<T> = {
|
|
|
45
45
|
[K in keyof T as DelimiterCase<K, '#'>]: T[K]
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
type SomeOptions = {
|
|
49
49
|
dryRun: boolean;
|
|
50
50
|
includeFile: string;
|
|
51
51
|
foo: number;
|
|
52
|
-
}
|
|
52
|
+
};
|
|
53
53
|
|
|
54
54
|
const rawCliOptions: OddlyCasedProperties<SomeOptions> = {
|
|
55
55
|
'dry#run': true,
|
|
56
56
|
'include#file': 'bar.js',
|
|
57
|
-
foo: 123
|
|
57
|
+
foo: 123,
|
|
58
58
|
};
|
|
59
59
|
```
|
|
60
60
|
|
|
@@ -15,19 +15,19 @@ This can be useful when, for example, converting some API types from a different
|
|
|
15
15
|
```
|
|
16
16
|
import type {DelimiterCasedPropertiesDeep} from 'type-fest';
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
type User = {
|
|
19
19
|
userId: number;
|
|
20
20
|
userName: string;
|
|
21
|
-
}
|
|
21
|
+
};
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
type UserWithFriends = {
|
|
24
24
|
userInfo: User;
|
|
25
25
|
userFriends: User[];
|
|
26
|
-
}
|
|
26
|
+
};
|
|
27
27
|
|
|
28
28
|
const result: DelimiterCasedPropertiesDeep<UserWithFriends, '-'> = {
|
|
29
29
|
'user-info': {
|
|
30
|
-
|
|
30
|
+
'user-id': 1,
|
|
31
31
|
'user-name': 'Tom',
|
|
32
32
|
},
|
|
33
33
|
'user-friends': [
|
|
@@ -42,7 +42,7 @@ const result: DelimiterCasedPropertiesDeep<UserWithFriends, '-'> = {
|
|
|
42
42
|
],
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
const splitOnNumbers: DelimiterCasedPropertiesDeep<{line1: {
|
|
45
|
+
const splitOnNumbers: DelimiterCasedPropertiesDeep<{line1: {line2: [{line3: string}]}}, '-', {splitOnNumbers: true}> = {
|
|
46
46
|
'line-1': {
|
|
47
47
|
'line-2': [
|
|
48
48
|
{
|
|
@@ -14,10 +14,10 @@ This can be useful when, for example, converting some API types from a different
|
|
|
14
14
|
```
|
|
15
15
|
import type {DelimiterCasedProperties} from 'type-fest';
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
type User = {
|
|
18
18
|
userId: number;
|
|
19
19
|
userName: string;
|
|
20
|
-
}
|
|
20
|
+
};
|
|
21
21
|
|
|
22
22
|
const result: DelimiterCasedProperties<User, '-'> = {
|
|
23
23
|
'user-id': 1,
|
|
@@ -25,15 +25,16 @@ type Union = A | B;
|
|
|
25
25
|
type OmittedUnion = Omit<Union, 'foo'>;
|
|
26
26
|
//=> {discriminant: 'A' | 'B'}
|
|
27
27
|
|
|
28
|
-
const omittedUnion: OmittedUnion
|
|
28
|
+
declare const omittedUnion: OmittedUnion;
|
|
29
29
|
|
|
30
30
|
if (omittedUnion.discriminant === 'A') {
|
|
31
31
|
// We would like to narrow `omittedUnion`'s type
|
|
32
32
|
// to `A` here, but we can't because `Omit`
|
|
33
33
|
// doesn't distribute over unions.
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
// @ts-expect-error
|
|
36
|
+
const aValue = omittedUnion.a;
|
|
37
|
+
//=> Error: `a` is not a property of `{discriminant: 'A' | 'B'}`
|
|
37
38
|
}
|
|
38
39
|
```
|
|
39
40
|
|
|
@@ -41,6 +42,8 @@ While `Except` solves this problem, it restricts the keys you can omit to the on
|
|
|
41
42
|
|
|
42
43
|
@example
|
|
43
44
|
```
|
|
45
|
+
import type {DistributedOmit} from 'type-fest';
|
|
46
|
+
|
|
44
47
|
type A = {
|
|
45
48
|
discriminant: 'A';
|
|
46
49
|
foo: string;
|
|
@@ -67,17 +70,19 @@ type Union = A | B | C;
|
|
|
67
70
|
|
|
68
71
|
type OmittedUnion = DistributedOmit<Union, 'foo' | 'bar'>;
|
|
69
72
|
|
|
70
|
-
const omittedUnion: OmittedUnion
|
|
73
|
+
declare const omittedUnion: OmittedUnion;
|
|
71
74
|
|
|
72
75
|
if (omittedUnion.discriminant === 'A') {
|
|
73
|
-
omittedUnion.a;
|
|
74
|
-
|
|
76
|
+
const aValue = omittedUnion.a;
|
|
77
|
+
//=> OK
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
// @ts-expect-error
|
|
80
|
+
const fooValue = omittedUnion.foo;
|
|
81
|
+
//=> Error: `foo` is not a property of `{discriminant: 'A'; a: string}`
|
|
78
82
|
|
|
79
|
-
|
|
80
|
-
|
|
83
|
+
// @ts-expect-error
|
|
84
|
+
const barValue = omittedUnion.bar;
|
|
85
|
+
//=> Error: `bar` is not a property of `{discriminant: 'A'; a: string}`
|
|
81
86
|
}
|
|
82
87
|
```
|
|
83
88
|
|
|
@@ -27,20 +27,23 @@ type Union = A | B;
|
|
|
27
27
|
type PickedUnion = Pick<Union, 'discriminant' | 'foo'>;
|
|
28
28
|
//=> {discriminant: 'A' | 'B', foo: {bar: string} | {baz: string}}
|
|
29
29
|
|
|
30
|
-
const pickedUnion: PickedUnion
|
|
30
|
+
declare const pickedUnion: PickedUnion;
|
|
31
31
|
|
|
32
32
|
if (pickedUnion.discriminant === 'A') {
|
|
33
33
|
// We would like to narrow `pickedUnion`'s type
|
|
34
34
|
// to `A` here, but we can't because `Pick`
|
|
35
35
|
// doesn't distribute over unions.
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
// @ts-expect-error
|
|
38
|
+
const barValue = pickedUnion.foo.bar;
|
|
38
39
|
//=> Error: Property 'bar' does not exist on type '{bar: string} | {baz: string}'.
|
|
39
40
|
}
|
|
40
41
|
```
|
|
41
42
|
|
|
42
43
|
@example
|
|
43
44
|
```
|
|
45
|
+
import type {DistributedPick} from 'type-fest';
|
|
46
|
+
|
|
44
47
|
type A = {
|
|
45
48
|
discriminant: 'A';
|
|
46
49
|
foo: {
|
|
@@ -63,16 +66,18 @@ type Union = A | B;
|
|
|
63
66
|
|
|
64
67
|
type PickedUnion = DistributedPick<Union, 'discriminant' | 'foo'>;
|
|
65
68
|
|
|
66
|
-
const pickedUnion: PickedUnion
|
|
69
|
+
declare const pickedUnion: PickedUnion;
|
|
67
70
|
|
|
68
71
|
if (pickedUnion.discriminant === 'A') {
|
|
69
|
-
pickedUnion.foo.bar;
|
|
70
|
-
|
|
72
|
+
const barValue = pickedUnion.foo.bar;
|
|
73
|
+
//=> OK
|
|
71
74
|
|
|
72
|
-
|
|
75
|
+
// @ts-expect-error
|
|
76
|
+
const extraneousValue = pickedUnion.extraneous;
|
|
73
77
|
//=> Error: Property `extraneous` does not exist on type `Pick<A, 'discriminant' | 'foo'>`.
|
|
74
78
|
|
|
75
|
-
|
|
79
|
+
// @ts-expect-error
|
|
80
|
+
const bazValue = pickedUnion.foo.baz;
|
|
76
81
|
//=> Error: `bar` is not a property of `{discriminant: 'A'; a: string}`.
|
|
77
82
|
}
|
|
78
83
|
```
|
package/source/empty-object.d.ts
CHANGED
|
@@ -17,8 +17,11 @@ const foo4: {} = {a: 1}; // Pass
|
|
|
17
17
|
|
|
18
18
|
// With `EmptyObject` only the first case is valid.
|
|
19
19
|
const bar1: EmptyObject = {}; // Pass
|
|
20
|
-
|
|
21
|
-
const
|
|
20
|
+
// @ts-expect-error
|
|
21
|
+
const bar2: EmptyObject = []; // Fail
|
|
22
|
+
// @ts-expect-error
|
|
23
|
+
const bar3: EmptyObject = 42; // Fail
|
|
24
|
+
// @ts-expect-error
|
|
22
25
|
const bar4: EmptyObject = {a: 1}; // Fail
|
|
23
26
|
```
|
|
24
27
|
|
|
@@ -36,8 +39,8 @@ Returns a `boolean` for whether the type is strictly equal to an empty plain obj
|
|
|
36
39
|
import type {IsEmptyObject} from 'type-fest';
|
|
37
40
|
|
|
38
41
|
type Pass = IsEmptyObject<{}>; //=> true
|
|
39
|
-
type
|
|
40
|
-
type
|
|
42
|
+
type Fail1 = IsEmptyObject<[]>; //=> false
|
|
43
|
+
type Fail2 = IsEmptyObject<null>; //=> false
|
|
41
44
|
```
|
|
42
45
|
|
|
43
46
|
@see {@link EmptyObject}
|
package/source/entries.d.ts
CHANGED
|
@@ -16,16 +16,16 @@ For example the {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/R
|
|
|
16
16
|
```
|
|
17
17
|
import type {Entries} from 'type-fest';
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
type Example = {
|
|
20
20
|
someKey: number;
|
|
21
|
-
}
|
|
21
|
+
};
|
|
22
22
|
|
|
23
23
|
const manipulatesEntries = (examples: Entries<Example>) => examples.map(example => [
|
|
24
24
|
// Does some arbitrary processing on the key (with type information available)
|
|
25
25
|
example[0].toUpperCase(),
|
|
26
26
|
|
|
27
27
|
// Does some arbitrary processing on the value (with type information available)
|
|
28
|
-
example[1].toFixed()
|
|
28
|
+
example[1].toFixed(0),
|
|
29
29
|
]);
|
|
30
30
|
|
|
31
31
|
const example: Example = {someKey: 1};
|
package/source/entry.d.ts
CHANGED
|
@@ -17,16 +17,16 @@ For example the {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/R
|
|
|
17
17
|
```
|
|
18
18
|
import type {Entry} from 'type-fest';
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
type Example = {
|
|
21
21
|
someKey: number;
|
|
22
|
-
}
|
|
22
|
+
};
|
|
23
23
|
|
|
24
24
|
const manipulatesEntry = (example: Entry<Example>) => [
|
|
25
25
|
// Does some arbitrary processing on the key (with type information available)
|
|
26
26
|
example[0].toUpperCase(),
|
|
27
27
|
|
|
28
28
|
// Does some arbitrary processing on the value (with type information available)
|
|
29
|
-
example[1].toFixed(),
|
|
29
|
+
example[1].toFixed(0),
|
|
30
30
|
];
|
|
31
31
|
|
|
32
32
|
const example: Example = {someKey: 1};
|