type-fest 5.3.0 → 5.4.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 +3 -0
- package/package.json +4 -4
- package/readme.md +5 -0
- package/source/all-extend.d.ts +9 -6
- package/source/array-reverse.d.ts +84 -0
- package/source/array-slice.d.ts +1 -1
- package/source/array-splice.d.ts +3 -3
- package/source/conditional-pick-deep.d.ts +1 -1
- package/source/conditional-simplify-deep.d.ts +3 -3
- package/source/distributed-omit.d.ts +4 -4
- package/source/distributed-pick.d.ts +5 -5
- package/source/exact.d.ts +1 -1
- package/source/except.d.ts +5 -5
- package/source/exclusify-union.d.ts +41 -7
- package/source/fixed-length-array.d.ts +6 -6
- package/source/get.d.ts +9 -3
- package/source/int-closed-range.d.ts +2 -2
- package/source/int-range.d.ts +2 -2
- package/source/internal/object.d.ts +25 -1
- package/source/is-literal.d.ts +3 -2
- package/source/is-never.d.ts +2 -2
- package/source/is-unknown.d.ts +1 -1
- package/source/jsonifiable.d.ts +3 -5
- package/source/key-as-string.d.ts +1 -1
- package/source/merge-deep.d.ts +7 -7
- package/source/merge-exclusive.d.ts +3 -3
- package/source/merge.d.ts +4 -1
- package/source/non-empty-string.d.ts +3 -3
- package/source/non-empty-tuple.d.ts +2 -2
- package/source/numeric.d.ts +3 -3
- package/source/object-merge.d.ts +194 -0
- package/source/omit-deep.d.ts +6 -22
- package/source/omit-index-signature.d.ts +8 -4
- package/source/override-properties.d.ts +1 -1
- package/source/package-json.d.ts +1 -1
- package/source/paths.d.ts +1 -1
- package/source/readonly-tuple.d.ts +2 -2
- package/source/required-deep.d.ts +2 -1
- package/source/schema.d.ts +10 -7
- package/source/set-non-nullable-deep.d.ts +1 -1
- package/source/set-parameter-type.d.ts +7 -7
- package/source/set-required-deep.d.ts +1 -7
- package/source/set-return-type.d.ts +1 -1
- package/source/split-on-rest-element.d.ts +2 -2
- package/source/subtract.d.ts +1 -1
- package/source/sum.d.ts +1 -1
- package/source/tuple-of.d.ts +1 -1
- package/source/tuple-to-object.d.ts +6 -6
- package/source/tuple-to-union.d.ts +1 -1
- package/source/union-to-intersection.d.ts +1 -1
- package/source/unknown-record.d.ts +6 -6
- package/source/unwrap-partial.d.ts +33 -0
- package/source/value-of.d.ts +2 -2
- package/source/words.d.ts +2 -2
package/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export type {TaggedUnion} from './source/tagged-union.d.ts';
|
|
|
22
22
|
export type {Writable} from './source/writable.d.ts';
|
|
23
23
|
export type {WritableDeep} from './source/writable-deep.d.ts';
|
|
24
24
|
export type {Merge} from './source/merge.d.ts';
|
|
25
|
+
export type {ObjectMerge} from './source/object-merge.d.ts';
|
|
25
26
|
export type {MergeDeep, MergeDeepOptions} from './source/merge-deep.d.ts';
|
|
26
27
|
export type {MergeExclusive} from './source/merge-exclusive.d.ts';
|
|
27
28
|
export type {RequireAtLeastOne} from './source/require-at-least-one.d.ts';
|
|
@@ -32,6 +33,7 @@ export type {SingleKeyObject} from './source/single-key-object.d.ts';
|
|
|
32
33
|
export type {OmitIndexSignature} from './source/omit-index-signature.d.ts';
|
|
33
34
|
export type {PickIndexSignature} from './source/pick-index-signature.d.ts';
|
|
34
35
|
export type {PartialDeep, PartialDeepOptions} from './source/partial-deep.d.ts';
|
|
36
|
+
export type {UnwrapPartial} from './source/unwrap-partial.d.ts';
|
|
35
37
|
export type {RequiredDeep} from './source/required-deep.d.ts';
|
|
36
38
|
export type {PickDeep} from './source/pick-deep.d.ts';
|
|
37
39
|
export type {OmitDeep} from './source/omit-deep.d.ts';
|
|
@@ -164,6 +166,7 @@ export type {IsOptional} from './source/is-optional.d.ts';
|
|
|
164
166
|
export type {IsNullable} from './source/is-nullable.d.ts';
|
|
165
167
|
export type {TupleOf} from './source/tuple-of.d.ts';
|
|
166
168
|
export type {ExclusifyUnion} from './source/exclusify-union.d.ts';
|
|
169
|
+
export type {ArrayReverse} from './source/array-reverse.d.ts';
|
|
167
170
|
|
|
168
171
|
// Template literal types
|
|
169
172
|
export type {CamelCase, CamelCaseOptions} from './source/camel-case.d.ts';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "type-fest",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.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,9 +25,9 @@
|
|
|
25
25
|
"node": ">=20"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
|
-
"test:tsc": "node --max-old-space-size=
|
|
29
|
-
"test:tsd": "tsd",
|
|
30
|
-
"test:xo": "xo",
|
|
28
|
+
"test:tsc": "node --max-old-space-size=6144 ./node_modules/.bin/tsc",
|
|
29
|
+
"test:tsd": "node --max-old-space-size=6144 ./node_modules/.bin/tsd",
|
|
30
|
+
"test:xo": "node --max-old-space-size=6144 ./node_modules/.bin/xo",
|
|
31
31
|
"test:linter": "node --test",
|
|
32
32
|
"test": "run-p test:*"
|
|
33
33
|
},
|
package/readme.md
CHANGED
|
@@ -106,6 +106,7 @@ Click the type names for complete docs.
|
|
|
106
106
|
- [`Writable`](source/writable.d.ts) - Create a type that strips `readonly` from the given type. Inverse of `Readonly<T>`.
|
|
107
107
|
- [`WritableDeep`](source/writable-deep.d.ts) - Create a deeply mutable version of an `object`/`ReadonlyMap`/`ReadonlySet`/`ReadonlyArray` type. The inverse of `ReadonlyDeep<T>`. Use `Writable<T>` if you only need one level deep.
|
|
108
108
|
- [`Merge`](source/merge.d.ts) - Merge two types into a new type. Keys of the second type overrides keys of the first type.
|
|
109
|
+
- [`ObjectMerge`](source/object-merge.d.ts) - Merge two object types into a new object type, where keys from the second override keys from the first.
|
|
109
110
|
- [`MergeDeep`](source/merge-deep.d.ts) - Merge two objects or two arrays/tuples recursively into a new type.
|
|
110
111
|
- [`MergeExclusive`](source/merge-exclusive.d.ts) - Create a type that has mutually exclusive keys.
|
|
111
112
|
- [`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.
|
|
@@ -122,6 +123,7 @@ Click the type names for complete docs.
|
|
|
122
123
|
- [`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.
|
|
123
124
|
- [`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.
|
|
124
125
|
- [`UndefinedOnPartialDeep`](source/undefined-on-partial-deep.d.ts) - Create a deep version of another type where all optional keys are set to also accept `undefined`.
|
|
126
|
+
- [`UnwrapPartial`](source/unwrap-partial.d.ts) - Revert the `Partial` modifier on an object type.
|
|
125
127
|
- [`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.
|
|
126
128
|
- [`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).
|
|
127
129
|
- [`Tagged`](source/tagged.d.ts) - Create a [tagged type](https://medium.com/@KevinBGreene/surviving-the-typescript-ecosystem-branding-and-type-tagging-6cf6e516523d) that can support [multiple tags](https://github.com/sindresorhus/type-fest/issues/665) and [per-tag metadata](https://medium.com/@ethanresnick/advanced-typescript-tagged-types-improved-with-type-level-metadata-5072fc125fcf). (This replaces the previous [`Opaque`](source/tagged.d.ts) type, which is now deprecated.)
|
|
@@ -263,6 +265,7 @@ Click the type names for complete docs.
|
|
|
263
265
|
- [`SplitOnRestElement`](source/split-on-rest-element.d.ts) - Splits an array into three parts, where the first contains all elements before the rest element, the second is the [`rest`](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types) element itself, and the third contains all elements after the rest element.
|
|
264
266
|
- [`ExtractRestElement`](source/extract-rest-element.d.ts) - Extract the [`rest`](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types) element type from an array.
|
|
265
267
|
- [`ExcludeRestElement`](source/exclude-rest-element.d.ts) - Create a tuple with the [`rest`](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types) element removed.
|
|
268
|
+
- [`ArrayReverse`](source/array-reverse.d.ts) - Reverse the order of elements in a tuple type.
|
|
266
269
|
|
|
267
270
|
### Numeric
|
|
268
271
|
|
|
@@ -474,6 +477,8 @@ There are many advanced types most users don't know about.
|
|
|
474
477
|
// NodeConfig interface.
|
|
475
478
|
new NodeAppBuilder().config({appName: 'ToDoApp'});
|
|
476
479
|
```
|
|
480
|
+
|
|
481
|
+
`Partial<T>` can be reverted with [`UnwrapPartial`](source/unwrap-partial.d.ts).
|
|
477
482
|
</details>
|
|
478
483
|
|
|
479
484
|
- [`Required<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype) - Make all properties in `T` required.
|
package/source/all-extend.d.ts
CHANGED
|
@@ -78,18 +78,21 @@ type D = AllExtend<[true, boolean, true], true>;
|
|
|
78
78
|
Note: Behaviour of optional elements depend on the `exactOptionalPropertyTypes` compiler option. When the option is disabled, the target type must include `undefined` for a successful match.
|
|
79
79
|
|
|
80
80
|
```
|
|
81
|
+
// @exactOptionalPropertyTypes: true
|
|
81
82
|
import type {AllExtend} from 'type-fest';
|
|
82
83
|
|
|
83
|
-
// `exactOptionalPropertyTypes` enabled
|
|
84
84
|
type A = AllExtend<[1?, 2?, 3?], number>;
|
|
85
85
|
//=> true
|
|
86
|
+
```
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
```
|
|
89
|
+
// @exactOptionalPropertyTypes: false
|
|
90
|
+
import type {AllExtend} from 'type-fest';
|
|
91
|
+
|
|
92
|
+
type A = AllExtend<[1?, 2?, 3?], number>;
|
|
93
|
+
//=> boolean
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
type C = AllExtend<[1?, 2?, 3?], number | undefined>;
|
|
95
|
+
type B = AllExtend<[1?, 2?, 3?], number | undefined>;
|
|
93
96
|
//=> true
|
|
94
97
|
```
|
|
95
98
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type {If} from './if.d.ts';
|
|
2
|
+
import type {IsArrayReadonly} from './internal/array.d.ts';
|
|
3
|
+
import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled} from './internal/type.d.ts';
|
|
4
|
+
import type {IsOptionalKeyOf} from './is-optional-key-of.d.ts';
|
|
5
|
+
import type {UnknownArray} from './unknown-array.d.ts';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
Reverse the order of elements in a tuple type.
|
|
9
|
+
|
|
10
|
+
@example
|
|
11
|
+
```ts
|
|
12
|
+
import type {ArrayReverse} from 'type-fest';
|
|
13
|
+
|
|
14
|
+
type A = ArrayReverse<[string, number, boolean]>;
|
|
15
|
+
//=> [boolean, number, string]
|
|
16
|
+
|
|
17
|
+
type B = ArrayReverse<readonly [string, number, ...boolean[]]>;
|
|
18
|
+
//=> readonly [...boolean[], number, string]
|
|
19
|
+
|
|
20
|
+
type C = ArrayReverse<['foo', 'bar'] | readonly [1, 2, 3]>;
|
|
21
|
+
//=> ['bar', 'foo'] | readonly [3, 2, 1]
|
|
22
|
+
|
|
23
|
+
type D = ArrayReverse<string[]>;
|
|
24
|
+
//=> string[]
|
|
25
|
+
|
|
26
|
+
type E = ArrayReverse<[]>;
|
|
27
|
+
//=> []
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Note: If the tuple contains optional elements, the result will be a union of tuples, refer to the examples below:
|
|
31
|
+
|
|
32
|
+
@example
|
|
33
|
+
```ts
|
|
34
|
+
import type {ArrayReverse} from 'type-fest';
|
|
35
|
+
|
|
36
|
+
type A = ArrayReverse<[string, number, boolean?]>;
|
|
37
|
+
//=> [number, string] | [boolean, number, string]
|
|
38
|
+
|
|
39
|
+
type B = ArrayReverse<[string, number?, boolean?]>;
|
|
40
|
+
//=> [string] | [number, string] | [boolean, number, string]
|
|
41
|
+
|
|
42
|
+
type C = ArrayReverse<[string?, number?, boolean?]>;
|
|
43
|
+
//=> [] | [string] | [number, string] | [boolean, number, string]
|
|
44
|
+
|
|
45
|
+
type D = ArrayReverse<[string, number?, ...boolean[]]>;
|
|
46
|
+
//=> [string] | [...boolean[], number, string]
|
|
47
|
+
|
|
48
|
+
type E = ArrayReverse<[string?, number?, ...boolean[]]>;
|
|
49
|
+
//=> [] | [string] | [...boolean[], number, string]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
@category Array
|
|
53
|
+
*/
|
|
54
|
+
export type ArrayReverse<TArray extends UnknownArray> = IfNotAnyOrNever<TArray,
|
|
55
|
+
TArray extends unknown // For distributing `TArray`
|
|
56
|
+
? _ArrayReverse<TArray> extends infer Result
|
|
57
|
+
? If<IsArrayReadonly<TArray>, Readonly<Result>, Result>
|
|
58
|
+
: never // Should never happen
|
|
59
|
+
: never>; // Should never happen
|
|
60
|
+
|
|
61
|
+
type _ArrayReverse<
|
|
62
|
+
TArray extends UnknownArray,
|
|
63
|
+
BeforeRestAcc extends UnknownArray = [],
|
|
64
|
+
AfterRestAcc extends UnknownArray = [],
|
|
65
|
+
Result extends UnknownArray = never,
|
|
66
|
+
> =
|
|
67
|
+
keyof TArray & `${number}` extends never
|
|
68
|
+
// Enters this branch, if `TArray` is empty (e.g., `[]`),
|
|
69
|
+
// or `TArray` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
|
|
70
|
+
? TArray extends readonly [...infer Rest, infer Last]
|
|
71
|
+
? _ArrayReverse<Rest, BeforeRestAcc, [...AfterRestAcc, Last], Result> // Accumulate elements that are present after the rest element in reverse order.
|
|
72
|
+
: Result | [...AfterRestAcc, ...TArray, ...BeforeRestAcc] // Add the rest element between the accumulated elements.
|
|
73
|
+
: TArray extends readonly [(infer First)?, ...infer Rest]
|
|
74
|
+
? IsOptionalKeyOf<TArray, '0'> extends true
|
|
75
|
+
? _ArrayReverse<
|
|
76
|
+
Rest,
|
|
77
|
+
[First | (If<IsExactOptionalPropertyTypesEnabled, never, undefined>), ...BeforeRestAcc], // Add `| undefined` for optional elements, if `exactOptionalPropertyTypes` is disabled.
|
|
78
|
+
AfterRestAcc,
|
|
79
|
+
Result | BeforeRestAcc
|
|
80
|
+
>
|
|
81
|
+
: _ArrayReverse<Rest, [First, ...BeforeRestAcc], AfterRestAcc, Result>
|
|
82
|
+
: never; // Should never happen, since `readonly [(infer First)?, ...infer Rest]` is a top-type for arrays.
|
|
83
|
+
|
|
84
|
+
export {};
|
package/source/array-slice.d.ts
CHANGED
package/source/array-splice.d.ts
CHANGED
|
@@ -76,15 +76,15 @@ import type {ArraySplice} from 'type-fest';
|
|
|
76
76
|
|
|
77
77
|
type SomeMonths0 = ['January', 'April', 'June'];
|
|
78
78
|
type Months0 = ArraySplice<SomeMonths0, 1, 0, ['Feb', 'March']>;
|
|
79
|
-
//=> ['January', 'Feb', 'March', 'April', 'June']
|
|
79
|
+
//=> ['January', 'Feb', 'March', 'April', 'June']
|
|
80
80
|
|
|
81
81
|
type SomeMonths1 = ['January', 'April', 'June'];
|
|
82
82
|
type Months1 = ArraySplice<SomeMonths1, 1, 1>;
|
|
83
|
-
//=> ['January', 'June']
|
|
83
|
+
//=> ['January', 'June']
|
|
84
84
|
|
|
85
85
|
type SomeMonths2 = ['January', 'Foo', 'April'];
|
|
86
86
|
type Months2 = ArraySplice<SomeMonths2, 1, 1, ['Feb', 'March']>;
|
|
87
|
-
//=> ['January', 'Feb', 'March', 'April']
|
|
87
|
+
//=> ['January', 'Feb', 'March', 'April']
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
@category Array
|
|
@@ -53,11 +53,11 @@ type TypeB = {
|
|
|
53
53
|
|
|
54
54
|
type SimplifyDeepTypeAB = ConditionalSimplifyDeep<TypeA & TypeB, SomeComplexType1 | SomeComplexType2, object>;
|
|
55
55
|
//=> {
|
|
56
|
-
//
|
|
56
|
+
// foo: {
|
|
57
57
|
// a: string;
|
|
58
|
-
// b: string;
|
|
59
58
|
// complexType: SomeComplexType1 & SomeComplexType2;
|
|
60
|
-
//
|
|
59
|
+
// b: string;
|
|
60
|
+
// };
|
|
61
61
|
// }
|
|
62
62
|
```
|
|
63
63
|
|
|
@@ -34,7 +34,7 @@ if (omittedUnion.discriminant === 'A') {
|
|
|
34
34
|
|
|
35
35
|
// @ts-expect-error
|
|
36
36
|
const aValue = omittedUnion.a;
|
|
37
|
-
|
|
37
|
+
// Error: `a` is not a property of `{discriminant: 'A' | 'B'}`
|
|
38
38
|
}
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -74,15 +74,15 @@ declare const omittedUnion: OmittedUnion;
|
|
|
74
74
|
|
|
75
75
|
if (omittedUnion.discriminant === 'A') {
|
|
76
76
|
const aValue = omittedUnion.a;
|
|
77
|
-
|
|
77
|
+
// OK
|
|
78
78
|
|
|
79
79
|
// @ts-expect-error
|
|
80
80
|
const fooValue = omittedUnion.foo;
|
|
81
|
-
|
|
81
|
+
// Error: `foo` is not a property of `{discriminant: 'A'; a: string}`
|
|
82
82
|
|
|
83
83
|
// @ts-expect-error
|
|
84
84
|
const barValue = omittedUnion.bar;
|
|
85
|
-
|
|
85
|
+
// Error: `bar` is not a property of `{discriminant: 'A'; a: string}`
|
|
86
86
|
}
|
|
87
87
|
```
|
|
88
88
|
|
|
@@ -25,7 +25,7 @@ type B = {
|
|
|
25
25
|
type Union = A | B;
|
|
26
26
|
|
|
27
27
|
type PickedUnion = Pick<Union, 'discriminant' | 'foo'>;
|
|
28
|
-
//=> {discriminant: 'A' | 'B'
|
|
28
|
+
//=> {discriminant: 'A' | 'B'; foo: {bar: string} | {baz: string}}
|
|
29
29
|
|
|
30
30
|
declare const pickedUnion: PickedUnion;
|
|
31
31
|
|
|
@@ -36,7 +36,7 @@ if (pickedUnion.discriminant === 'A') {
|
|
|
36
36
|
|
|
37
37
|
// @ts-expect-error
|
|
38
38
|
const barValue = pickedUnion.foo.bar;
|
|
39
|
-
|
|
39
|
+
// Error: Property 'bar' does not exist on type '{bar: string} | {baz: string}'.
|
|
40
40
|
}
|
|
41
41
|
```
|
|
42
42
|
|
|
@@ -70,15 +70,15 @@ declare const pickedUnion: PickedUnion;
|
|
|
70
70
|
|
|
71
71
|
if (pickedUnion.discriminant === 'A') {
|
|
72
72
|
const barValue = pickedUnion.foo.bar;
|
|
73
|
-
|
|
73
|
+
// OK
|
|
74
74
|
|
|
75
75
|
// @ts-expect-error
|
|
76
76
|
const extraneousValue = pickedUnion.extraneous;
|
|
77
|
-
|
|
77
|
+
// Error: Property `extraneous` does not exist on type `Pick<A, 'discriminant' | 'foo'>`.
|
|
78
78
|
|
|
79
79
|
// @ts-expect-error
|
|
80
80
|
const bazValue = pickedUnion.foo.baz;
|
|
81
|
-
|
|
81
|
+
// Error: `bar` is not a property of `{discriminant: 'A'; a: string}`.
|
|
82
82
|
}
|
|
83
83
|
```
|
|
84
84
|
|
package/source/exact.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ declare function onlyAcceptName(arguments_: OnlyAcceptName): void;
|
|
|
29
29
|
// TypeScript complains about excess properties when an object literal is provided.
|
|
30
30
|
// @ts-expect-error
|
|
31
31
|
onlyAcceptName({name: 'name', id: 1});
|
|
32
|
-
|
|
32
|
+
// `id` is excess
|
|
33
33
|
|
|
34
34
|
// TypeScript does not complain about excess properties when the provided value is a variable (not an object literal).
|
|
35
35
|
const invalidInput = {name: 'name', id: 1};
|
package/source/except.d.ts
CHANGED
|
@@ -68,14 +68,14 @@ type FooWithoutA = Except<Foo, 'a'>;
|
|
|
68
68
|
|
|
69
69
|
// @ts-expect-error
|
|
70
70
|
const fooWithoutA: FooWithoutA = {a: 1, b: '2'};
|
|
71
|
-
|
|
71
|
+
// errors: 'a' does not exist in type '{ b: string; }'
|
|
72
72
|
|
|
73
73
|
type FooWithoutB = Except<Foo, 'b', {requireExactProps: true}>;
|
|
74
|
-
//=> {a: number} & Partial<Record<
|
|
74
|
+
//=> {a: number} & Partial<Record<'b', never>>
|
|
75
75
|
|
|
76
76
|
// @ts-expect-error
|
|
77
77
|
const fooWithoutB: FooWithoutB = {a: 1, b: '2'};
|
|
78
|
-
|
|
78
|
+
// errors at 'b': Type 'string' is not assignable to type 'undefined'.
|
|
79
79
|
|
|
80
80
|
// The `Omit` utility type doesn't work when omitting specific keys from objects containing index signatures.
|
|
81
81
|
|
|
@@ -90,12 +90,12 @@ type UserData = {
|
|
|
90
90
|
|
|
91
91
|
// `Omit` clearly doesn't behave as expected in this case:
|
|
92
92
|
type PostPayload = Omit<UserData, 'email'>;
|
|
93
|
-
//=> {
|
|
93
|
+
//=> {[x: string]: string; [x: number]: string}
|
|
94
94
|
|
|
95
95
|
// In situations like this, `Except` works better.
|
|
96
96
|
// It simply removes the `email` key while preserving all the other keys.
|
|
97
97
|
type PostPayloadFixed = Except<UserData, 'email'>;
|
|
98
|
-
//=> {
|
|
98
|
+
//=> {[x: string]: string; name: string; role: 'admin' | 'user'}
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
@category Object
|
|
@@ -30,13 +30,19 @@ loadConfig1({filePath: './config.json', content: '{ "name": "app" }'}); // No er
|
|
|
30
30
|
|
|
31
31
|
// Use `ExclusifyUnion` to prevent that mistake.
|
|
32
32
|
type Config = ExclusifyUnion<FileConfig | InlineConfig>;
|
|
33
|
-
//=> {
|
|
33
|
+
//=> {
|
|
34
|
+
// filePath: string;
|
|
35
|
+
// content?: never;
|
|
36
|
+
// } | {
|
|
37
|
+
// content: string;
|
|
38
|
+
// filePath?: never;
|
|
39
|
+
// }
|
|
34
40
|
|
|
35
41
|
declare function loadConfig2(options: Config): void;
|
|
36
42
|
|
|
37
43
|
// @ts-expect-error
|
|
38
44
|
loadConfig2({filePath: './config.json', content: '{ "name": "app" }'});
|
|
39
|
-
|
|
45
|
+
// Error: Argument of type '{ filePath: string; content: string; }' is not assignable to parameter of type '{ filePath: string; content?: never; } | { content: string; filePath?: never; }'.
|
|
40
46
|
|
|
41
47
|
loadConfig2({filePath: './config.json'}); // Ok
|
|
42
48
|
|
|
@@ -63,7 +69,15 @@ function processPayment1(payment: CardPayment | PaypalPayment) {
|
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
type Payment = ExclusifyUnion<CardPayment | PaypalPayment>;
|
|
66
|
-
//=> {
|
|
72
|
+
//=> {
|
|
73
|
+
// amount: number;
|
|
74
|
+
// cardNumber: string;
|
|
75
|
+
// paypalId?: never;
|
|
76
|
+
// } | {
|
|
77
|
+
// amount: number;
|
|
78
|
+
// paypalId: string;
|
|
79
|
+
// cardNumber?: never;
|
|
80
|
+
// }
|
|
67
81
|
|
|
68
82
|
function processPayment2(payment: Payment) {
|
|
69
83
|
const details = payment.cardNumber ?? payment.paypalId; // Ok
|
|
@@ -76,16 +90,36 @@ function processPayment2(payment: Payment) {
|
|
|
76
90
|
import type {ExclusifyUnion} from 'type-fest';
|
|
77
91
|
|
|
78
92
|
type A = ExclusifyUnion<{a: string} | {b: number}>;
|
|
79
|
-
//=> {a: string; b?: never} | {a?: never
|
|
93
|
+
//=> {a: string; b?: never} | {b: number; a?: never}
|
|
80
94
|
|
|
81
95
|
type B = ExclusifyUnion<{a: string} | {b: number} | {c: boolean}>;
|
|
82
|
-
//=> {
|
|
96
|
+
//=> {
|
|
97
|
+
// a: string;
|
|
98
|
+
// b?: never;
|
|
99
|
+
// c?: never;
|
|
100
|
+
// } | {
|
|
101
|
+
// b: number;
|
|
102
|
+
// a?: never;
|
|
103
|
+
// c?: never;
|
|
104
|
+
// } | {
|
|
105
|
+
// c: boolean;
|
|
106
|
+
// a?: never;
|
|
107
|
+
// b?: never;
|
|
108
|
+
// }
|
|
83
109
|
|
|
84
110
|
type C = ExclusifyUnion<{a: string; b: number} | {b: string; c: number}>;
|
|
85
|
-
//=> {
|
|
111
|
+
//=> {
|
|
112
|
+
// a: string;
|
|
113
|
+
// b: number;
|
|
114
|
+
// c?: never;
|
|
115
|
+
// } | {
|
|
116
|
+
// b: string;
|
|
117
|
+
// c: number;
|
|
118
|
+
// a?: never;
|
|
119
|
+
// }
|
|
86
120
|
|
|
87
121
|
type D = ExclusifyUnion<{a?: 1; readonly b: 2} | {d: 4}>;
|
|
88
|
-
//=> {a?: 1; readonly b: 2; d?: never} | {a?: never; b?: never
|
|
122
|
+
//=> {a?: 1; readonly b: 2; d?: never} | {d: 4; a?: never; b?: never}
|
|
89
123
|
```
|
|
90
124
|
|
|
91
125
|
@category Object
|
|
@@ -34,7 +34,7 @@ const color: FixedLengthArray<number, 3> = [255, 128, 64];
|
|
|
34
34
|
|
|
35
35
|
// @ts-expect-error
|
|
36
36
|
color.pop();
|
|
37
|
-
|
|
37
|
+
// Error: Property 'pop' does not exist on type 'FixedLengthArray<number, 3>'.
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Use-cases:
|
|
@@ -56,7 +56,7 @@ const blue = color[2];
|
|
|
56
56
|
|
|
57
57
|
// @ts-expect-error
|
|
58
58
|
const alpha = color[3];
|
|
59
|
-
|
|
59
|
+
// Error: Property '3' does not exist on type 'FixedLengthArray<number, 3>'.
|
|
60
60
|
|
|
61
61
|
// You can write to valid indices.
|
|
62
62
|
color[0] = 128;
|
|
@@ -66,19 +66,19 @@ color[2] = 32;
|
|
|
66
66
|
// But you cannot write to out-of-bounds indices.
|
|
67
67
|
// @ts-expect-error
|
|
68
68
|
color[3] = 0.5;
|
|
69
|
-
|
|
69
|
+
// Error: Property '3' does not exist on type 'FixedLengthArray<number, 3>'.
|
|
70
70
|
|
|
71
71
|
// @ts-expect-error
|
|
72
72
|
color.push(0.5);
|
|
73
|
-
|
|
73
|
+
// Error: Property 'push' does not exist on type 'FixedLengthArray<number, 3>'.
|
|
74
74
|
|
|
75
75
|
// @ts-expect-error
|
|
76
76
|
color = [0, 128, 255, 0.5];
|
|
77
|
-
|
|
77
|
+
// Error: Type '[number, number, number, number]' is not assignable to type 'FixedLengthArray<number, 3>'. Types of property 'length' are incompatible.
|
|
78
78
|
|
|
79
79
|
// @ts-expect-error
|
|
80
80
|
color.length = 4;
|
|
81
|
-
|
|
81
|
+
// Error: Cannot assign to 'length' because it is a read-only property.
|
|
82
82
|
|
|
83
83
|
function toHex([r, g, b]: readonly [number, number, number]) {
|
|
84
84
|
return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`;
|
package/source/get.d.ts
CHANGED
|
@@ -187,18 +187,24 @@ type ApiResponse = {
|
|
|
187
187
|
};
|
|
188
188
|
|
|
189
189
|
const getName = (apiResponse: ApiResponse) => get(apiResponse, 'hits.hits[0]._source.name');
|
|
190
|
-
//=> (apiResponse: ApiResponse) => {
|
|
190
|
+
//=> (apiResponse: ApiResponse) => {
|
|
191
|
+
// given: string[];
|
|
192
|
+
// family: string;
|
|
193
|
+
// }[] | undefined
|
|
191
194
|
|
|
192
195
|
// Path also supports a readonly array of strings
|
|
193
196
|
const getNameWithPathArray = (apiResponse: ApiResponse) => get(apiResponse, ['hits', 'hits', '0', '_source', 'name']);
|
|
194
|
-
//=> (apiResponse: ApiResponse) => {
|
|
197
|
+
//=> (apiResponse: ApiResponse) => {
|
|
198
|
+
// given: string[];
|
|
199
|
+
// family: string;
|
|
200
|
+
// }[] | undefined
|
|
195
201
|
|
|
196
202
|
// Non-strict mode:
|
|
197
203
|
type A = Get<string[], '3', {strict: false}>;
|
|
198
204
|
//=> string
|
|
199
205
|
|
|
200
206
|
type B = Get<Record<string, string>, 'foo', {strict: true}>;
|
|
201
|
-
|
|
207
|
+
//=> string | undefined
|
|
202
208
|
```
|
|
203
209
|
|
|
204
210
|
@category Object
|
|
@@ -17,8 +17,8 @@ Use-cases:
|
|
|
17
17
|
```
|
|
18
18
|
import type {IntClosedRange} from 'type-fest';
|
|
19
19
|
|
|
20
|
-
type Age = IntClosedRange<0,
|
|
21
|
-
//=> 0 | 1 | 2 |
|
|
20
|
+
type Age = IntClosedRange<0, 20>;
|
|
21
|
+
//=> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20
|
|
22
22
|
|
|
23
23
|
type FontSize = IntClosedRange<10, 20>;
|
|
24
24
|
//=> 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20
|
package/source/int-range.d.ts
CHANGED
|
@@ -17,8 +17,8 @@ Use-cases:
|
|
|
17
17
|
```
|
|
18
18
|
import type {IntRange} from 'type-fest';
|
|
19
19
|
|
|
20
|
-
type Age = IntRange<0,
|
|
21
|
-
//=> 0 | 1 | 2 |
|
|
20
|
+
type Age = IntRange<0, 20>;
|
|
21
|
+
//=> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19
|
|
22
22
|
|
|
23
23
|
type FontSize = IntRange<10, 20>;
|
|
24
24
|
//=> 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19
|
|
@@ -9,7 +9,7 @@ import type {If} from '../if.d.ts';
|
|
|
9
9
|
import type {IsNever} from '../is-never.d.ts';
|
|
10
10
|
import type {FilterDefinedKeys, FilterOptionalKeys} from './keys.d.ts';
|
|
11
11
|
import type {MapsSetsOrArrays, NonRecursiveType} from './type.d.ts';
|
|
12
|
-
import type {ToString} from './string.d.ts';
|
|
12
|
+
import type {StringToNumber, ToString} from './string.d.ts';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
Create an object type with the given key `<Key>` and value `<Value>`.
|
|
@@ -265,4 +265,28 @@ export type CollapseLiterals<T> = {} extends T
|
|
|
265
265
|
? U
|
|
266
266
|
: T;
|
|
267
267
|
|
|
268
|
+
/**
|
|
269
|
+
Normalize keys by including string and number representations wherever applicable.
|
|
270
|
+
|
|
271
|
+
@example
|
|
272
|
+
```ts
|
|
273
|
+
type A = NormalizedKeys<0 | '1'>;
|
|
274
|
+
//=> 0 | '0' | 1 | '1'
|
|
275
|
+
|
|
276
|
+
type B = NormalizedKeys<string>;
|
|
277
|
+
//=> string | number
|
|
278
|
+
|
|
279
|
+
type C = NormalizedKeys<number>;
|
|
280
|
+
//=> number | `${number}`
|
|
281
|
+
|
|
282
|
+
type D = NormalizedKeys<symbol | 'foo'>;
|
|
283
|
+
//=> symbol | 'foo'
|
|
284
|
+
```
|
|
285
|
+
*/
|
|
286
|
+
export type NormalizedKeys<Keys extends PropertyKey> =
|
|
287
|
+
| Keys
|
|
288
|
+
| (string extends Keys ? number : never)
|
|
289
|
+
| StringToNumber<Keys & string>
|
|
290
|
+
| ToString<Keys & number>;
|
|
291
|
+
|
|
268
292
|
export {};
|
package/source/is-literal.d.ts
CHANGED
|
@@ -207,7 +207,7 @@ const stringId = getId({asString: true});
|
|
|
207
207
|
|
|
208
208
|
declare const runtimeBoolean: boolean;
|
|
209
209
|
const eitherId = getId({asString: runtimeBoolean});
|
|
210
|
-
//=>
|
|
210
|
+
//=> string | number
|
|
211
211
|
```
|
|
212
212
|
|
|
213
213
|
@category Type Guard
|
|
@@ -236,7 +236,8 @@ function get<Object_ extends Record<symbol, number>, Key extends keyof Object_>(
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
const symbolLiteral = Symbol('literal');
|
|
239
|
-
|
|
239
|
+
let symbolValue = Symbol('value1');
|
|
240
|
+
symbolValue = Symbol('value2');
|
|
240
241
|
|
|
241
242
|
get({[symbolLiteral]: 1} as const, symbolLiteral);
|
|
242
243
|
//=> 1
|
package/source/is-never.d.ts
CHANGED
|
@@ -38,14 +38,14 @@ type IsTrue<T> = T extends true ? true : false;
|
|
|
38
38
|
|
|
39
39
|
// When a distributive conditional is instantiated with `never`, the entire conditional results in `never`.
|
|
40
40
|
type A = IsTrue<never>;
|
|
41
|
-
|
|
41
|
+
//=> never
|
|
42
42
|
|
|
43
43
|
// If you don't want that behaviour, you can explicitly add an `IsNever` check before the distributive conditional.
|
|
44
44
|
type IsTrueFixed<T> =
|
|
45
45
|
IsNever<T> extends true ? false : T extends true ? true : false;
|
|
46
46
|
|
|
47
47
|
type B = IsTrueFixed<never>;
|
|
48
|
-
|
|
48
|
+
//=> false
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
@category Type Guard
|
package/source/is-unknown.d.ts
CHANGED
package/source/jsonifiable.d.ts
CHANGED
|
@@ -19,17 +19,15 @@ const error: Jsonifiable = {
|
|
|
19
19
|
map: new Map([['a', 1]]),
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
JSON.stringify(error);
|
|
23
|
-
//=> {"map": {}}
|
|
22
|
+
console.log(JSON.stringify(error)); // {"map": {}}
|
|
24
23
|
|
|
25
24
|
const good: Jsonifiable = {
|
|
26
25
|
number: 3,
|
|
27
|
-
date: new Date(),
|
|
26
|
+
date: new Date('2025-12-25'),
|
|
28
27
|
missing: undefined,
|
|
29
28
|
};
|
|
30
29
|
|
|
31
|
-
JSON.stringify(good);
|
|
32
|
-
//=> {"number": 3, "date": "2022-10-17T22:22:35.920Z"}
|
|
30
|
+
console.log(JSON.stringify(good)); // {"number": 3, "date": "2025-12-25T00:00:00.000Z"}
|
|
33
31
|
```
|
|
34
32
|
|
|
35
33
|
@category JSON
|