type-fest 4.3.3 → 4.5.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 CHANGED
@@ -5,6 +5,7 @@ export * from './source/basic';
5
5
  export * from './source/observable-like';
6
6
 
7
7
  // Utilities
8
+ export type {KeysOfUnion} from './source/keys-of-union';
8
9
  export type {EmptyObject, IsEmptyObject} from './source/empty-object';
9
10
  export type {NonEmptyObject} from './source/non-empty-object';
10
11
  export type {UnknownRecord} from './source/unknown-record';
@@ -24,6 +25,7 @@ export type {PickIndexSignature} from './source/pick-index-signature';
24
25
  export type {PartialDeep, PartialDeepOptions} from './source/partial-deep';
25
26
  export type {RequiredDeep} from './source/required-deep';
26
27
  export type {PartialOnUndefinedDeep, PartialOnUndefinedDeepOptions} from './source/partial-on-undefined-deep';
28
+ export type {UndefinedOnPartialDeep} from './source/undefined-on-partial-deep';
27
29
  export type {ReadonlyDeep} from './source/readonly-deep';
28
30
  export type {LiteralUnion} from './source/literal-union';
29
31
  export type {Promisable} from './source/promisable';
@@ -81,6 +83,7 @@ export type {WritableKeysOf} from './source/writable-keys-of';
81
83
  export type {HasWritableKeys} from './source/has-writable-keys';
82
84
  export type {Spread} from './source/spread';
83
85
  export type {TupleToUnion} from './source/tuple-to-union';
86
+ export type {IntRange} from './source/int-range';
84
87
  export type {IsEqual} from './source/is-equal';
85
88
  export type {
86
89
  IsLiteral,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-fest",
3
- "version": "4.3.3",
3
+ "version": "4.5.0",
4
4
  "description": "A collection of essential TypeScript types",
5
5
  "license": "(MIT OR CC0-1.0)",
6
6
  "repository": "sindresorhus/type-fest",
@@ -15,7 +15,8 @@
15
15
  "node": ">=16"
16
16
  },
17
17
  "scripts": {
18
- "test": "xo && tsd && tsc && node script/test/source-files-extension.js"
18
+ "test": "xo && tsd && tsc && npm run test:undefined-on-partial-deep && node script/test/source-files-extension.js",
19
+ "test:undefined-on-partial-deep": "cd test-d/undefined-on-partial-deep && tsc --project tsconfig.json"
19
20
  },
20
21
  "files": [
21
22
  "index.d.ts",
package/readme.md CHANGED
@@ -129,6 +129,7 @@ Click the type names for complete docs.
129
129
  - [`PickIndexSignature`](source/pick-index-signature.d.ts) - Pick only index signatures from the given object type, leaving out all explicitly defined properties.
130
130
  - [`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.
131
131
  - [`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.
132
+ - [`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`.
132
133
  - [`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.
133
134
  - [`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).
134
135
  - [`Tagged`](source/opaque.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) if needed.
@@ -159,6 +160,7 @@ Click the type names for complete docs.
159
160
  - [`Schema`](source/schema.d.ts) - Create a deep version of another object type where property values are recursively replaced into a given value type.
160
161
  - [`Exact`](source/exact.d.ts) - Create a type that does not allow extra properties.
161
162
  - [`OptionalKeysOf`](source/optional-keys-of.d.ts) - Extract all optional keys from the given type.
163
+ - [`KeysOfUnion`](source/keys-of-union.d.ts) - Create a union of all keys from a given type, even those exclusive to specific union members.
162
164
  - [`HasOptionalKeys`](source/has-optional-keys.d.ts) - Create a `true`/`false` type depending on whether the given type has any optional fields.
163
165
  - [`RequiredKeysOf`](source/required-keys-of.d.ts) - Extract all required keys from the given type.
164
166
  - [`HasRequiredKeys`](source/has-required-keys.d.ts) - Create a `true`/`false` type depending on whether the given type has any required fields.
@@ -169,6 +171,7 @@ Click the type names for complete docs.
169
171
  - [`Spread`](source/spread.d.ts) - Mimic the type inferred by TypeScript when merging two objects or two arrays/tuples using the spread syntax.
170
172
  - [`IsEqual`](source/is-equal.d.ts) - Returns a boolean for whether the two given types are equal.
171
173
  - [`TaggedUnion`](source/tagged-union.d.ts) - Create a union of types that share a common discriminant property.
174
+ - [`IntRange`](source/int-range.d.ts) - Generate a union of numbers.
172
175
 
173
176
  ### Type Guard
174
177
 
@@ -293,13 +296,14 @@ type ShouldBeNever = IfAny<'not any', 'not never', 'never'>;
293
296
 
294
297
  *If you know one of our types by a different name, add it here for discovery.*
295
298
 
296
- - `Prettify`- See [`Simplify`](https://github.com/sindresorhus/type-fest/blob/main/source/simplify.d.ts)
297
- - `Expand`- See [`Simplify`](https://github.com/sindresorhus/type-fest/blob/main/source/simplify.d.ts)
298
- - `PartialBy` - See [`SetOptional`](https://github.com/sindresorhus/type-fest/blob/main/source/set-optional.d.ts)
299
- - `RecordDeep`- See [`Schema`](https://github.com/sindresorhus/type-fest/blob/main/source/schema.d.ts)
300
- - `Mutable`- See [`Writable`](https://github.com/sindresorhus/type-fest/blob/main/source/writable.d.ts)
301
- - `RequireOnlyOne` - See [`RequireExactlyOne`](https://github.com/sindresorhus/type-fest/blob/main/source/require-exactly-one.d.ts)
302
- - `AtMostOne` - See [`RequireOneOrNone`](https://github.com/sindresorhus/type-fest/blob/main/source/require-one-or-none.d.ts)
299
+ - `Prettify`- See [`Simplify`](source/simplify.d.ts)
300
+ - `Expand`- See [`Simplify`](source/simplify.d.ts)
301
+ - `PartialBy` - See [`SetOptional`](source/set-optional.d.ts)
302
+ - `RecordDeep`- See [`Schema`](source/schema.d.ts)
303
+ - `Mutable`- See [`Writable`](source/writable.d.ts)
304
+ - `RequireOnlyOne` - See [`RequireExactlyOne`](source/require-exactly-one.d.ts)
305
+ - `AtMostOne` - See [`RequireOneOrNone`](source/require-one-or-none.d.ts)
306
+ - `AllKeys` - See [`KeysOfUnion`](source/keys-of-union.d.ts)
303
307
 
304
308
  ## Tips
305
309
 
package/source/exact.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- import type {KeysOfUnion, ArrayElement, ObjectValue} from './internal';
1
+ import type {ArrayElement, ObjectValue} from './internal';
2
2
  import type {Opaque, TagContainer} from './opaque';
3
3
  import type {IsEqual} from './is-equal';
4
+ import type {KeysOfUnion} from './keys-of-union';
4
5
 
5
6
  /**
6
7
  Create a type from `ParameterType` and `InputType` and change keys exclusive to `InputType` to `never`.
@@ -0,0 +1,52 @@
1
+ import type {BuildTuple, Subtract} from './internal';
2
+
3
+ /**
4
+ Generate a union of numbers.
5
+
6
+ The numbers are created from the given `Start` (inclusive) parameter to the given `End` (exclusive) parameter.
7
+
8
+ You skip over numbers using the `Step` parameter (defaults to `1`). For example, `IntRange<0, 10, 2>` will create a union of `0 | 2 | 4 | 6 | 8`.
9
+
10
+ Note: `Start` or `End` must smaller than `1000`.
11
+
12
+ Use-cases:
13
+ 1. This can be used to define a set of valid input/output values. for example:
14
+ ```
15
+ type Age = IntRange<0, 120>;
16
+ type FontSize = IntRange<10, 20>;
17
+ type EvenNumber = IntRange<0, 11, 2>; //=> 0 | 2 | 4 | 6 | 8 | 10
18
+ ```
19
+ 2. This can be used to define random numbers in a range. For example, `type RandomNumber = IntRange<0, 100>;`
20
+
21
+ @example
22
+ ```
23
+ import type {IntRange} from 'type-fest';
24
+
25
+ // Create union type `0 | 1 | ... | 9`
26
+ type ZeroToNine = IntRange<0, 10>;
27
+
28
+ // Create union type `100 | 200 | 300 | ... | 900`
29
+ type Hundreds = IntRange<100, 901, 100>;
30
+ ```
31
+ */
32
+ export type IntRange<Start extends number, End extends number, Step extends number = 1> = PrivateIntRange<Start, End, Step>;
33
+
34
+ /**
35
+ The actual implementation of `IntRange`. It's private because it has some arguments that don't need to be exposed.
36
+ */
37
+ type PrivateIntRange<
38
+ Start extends number,
39
+ End extends number,
40
+ Step extends number,
41
+ Gap extends number = Subtract<Step, 1>, // The gap between each number, gap = step - 1
42
+ List extends unknown[] = BuildTuple<Start, never>, // The final `List` is `[...StartLengthTuple, ...[number, ...GapLengthTuple], ...[number, ...GapLengthTuple], ... ...]`, so can initialize the `List` with `[...StartLengthTuple]`
43
+ EndLengthTuple extends unknown[] = BuildTuple<End>,
44
+ > = Gap extends 0 ?
45
+ // Handle the case that without `Step`
46
+ List['length'] extends End // The result of "List[length] === End"
47
+ ? Exclude<List[number], never> // All unused elements are `never`, so exclude them
48
+ : PrivateIntRange<Start, End, Step, Gap, [...List, List['length'] ]>
49
+ // Handle the case that with `Step`
50
+ : List extends [...(infer U), ...EndLengthTuple] // The result of "List[length] >= End", because the `...BuildTuple<Gap, never>` maybe make `List` too long.
51
+ ? Exclude<List[number], never>
52
+ : PrivateIntRange<Start, End, Step, Gap, [...List, List['length'], ...BuildTuple<Gap, never>]>;
@@ -14,13 +14,15 @@ Infer the length of the given array `<T>`.
14
14
  type TupleLength<T extends readonly unknown[]> = T extends {readonly length: infer L} ? L : never;
15
15
 
16
16
  /**
17
- Create a tuple type of the given length `<L>`.
17
+ Create a tuple type of the given length `<L>` and fill it with the given type `<Fill>`.
18
+
19
+ If `<Fill>` is not provided, it will default to `unknown`.
18
20
 
19
21
  @link https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f
20
22
  */
21
- type BuildTuple<L extends number, T extends readonly unknown[] = []> = T extends {readonly length: L}
23
+ export type BuildTuple<L extends number, Fill = unknown, T extends readonly unknown[] = []> = T extends {readonly length: L}
22
24
  ? T
23
- : BuildTuple<L, [...T, unknown]>;
25
+ : BuildTuple<L, Fill, [...T, Fill]>;
24
26
 
25
27
  /**
26
28
  Create a tuple of length `A` and a tuple composed of two other tuples,
@@ -37,15 +39,6 @@ Matches any primitive, `Date`, or `RegExp` value.
37
39
  */
38
40
  export type BuiltIns = Primitive | Date | RegExp;
39
41
 
40
- /**
41
- Gets keys from a type. Similar to `keyof` but this one also works for union types.
42
-
43
- The reason a simple `keyof Union` does not work is because `keyof` always returns the accessible keys of a type. In the case of a union, that will only be the common keys.
44
-
45
- @link https://stackoverflow.com/a/49402091
46
- */
47
- export type KeysOfUnion<T> = T extends T ? keyof T : never;
48
-
49
42
  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';
50
43
 
51
44
  export type StringDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
@@ -96,24 +96,24 @@ export type Jsonify<T> = IsAny<T> extends true
96
96
  ? null
97
97
  : T extends JsonPrimitive
98
98
  ? T
99
- : // Instanced primitives are objects
100
- T extends Number
101
- ? number
102
- : T extends String
103
- ? string
104
- : T extends Boolean
105
- ? boolean
106
- : T extends Map<any, any> | Set<any>
107
- ? EmptyObject
108
- : T extends TypedArray
109
- ? Record<string, number>
110
- : T extends NotJsonable
111
- ? never // Non-JSONable type union was found not empty
112
- : // Any object with toJSON is special case
113
- T extends {toJSON(): infer J}
114
- ? (() => J) extends () => JsonValue // Is J assignable to JsonValue?
115
- ? J // Then T is Jsonable and its Jsonable value is J
116
- : Jsonify<J> // Maybe if we look a level deeper we'll find a JsonValue
99
+ : // Any object with toJSON is special case
100
+ T extends {toJSON(): infer J}
101
+ ? (() => J) extends () => JsonValue // Is J assignable to JsonValue?
102
+ ? J // Then T is Jsonable and its Jsonable value is J
103
+ : Jsonify<J> // Maybe if we look a level deeper we'll find a JsonValue
104
+ : // Instanced primitives are objects
105
+ T extends Number
106
+ ? number
107
+ : T extends String
108
+ ? string
109
+ : T extends Boolean
110
+ ? boolean
111
+ : T extends Map<any, any> | Set<any>
112
+ ? EmptyObject
113
+ : T extends TypedArray
114
+ ? Record<string, number>
115
+ : T extends NotJsonable
116
+ ? never // Non-JSONable type union was found not empty
117
117
  : T extends []
118
118
  ? []
119
119
  : T extends unknown[]
@@ -0,0 +1,40 @@
1
+ /**
2
+ Create a union of all keys from a given type, even those exclusive to specific union members.
3
+
4
+ Unlike the native `keyof` keyword, which returns keys present in **all** union members, this type returns keys from **any** member.
5
+
6
+ @link https://stackoverflow.com/a/49402091
7
+
8
+ @example
9
+ ```
10
+ import type {KeysOfUnion} from 'type-fest';
11
+
12
+ type A = {
13
+ common: string;
14
+ a: number;
15
+ };
16
+
17
+ type B = {
18
+ common: string;
19
+ b: string;
20
+ };
21
+
22
+ type C = {
23
+ common: string;
24
+ c: boolean;
25
+ };
26
+
27
+ type Union = A | B | C;
28
+
29
+ type CommonKeys = keyof Union;
30
+ //=> 'common'
31
+
32
+ type AllKeys = KeysOfUnion<Union>;
33
+ //=> 'common' | 'a' | 'b' | 'c'
34
+ ```
35
+
36
+ @category Object
37
+ */
38
+ export type KeysOfUnion<ObjectType> = ObjectType extends unknown
39
+ ? keyof ObjectType
40
+ : never;
@@ -25,5 +25,12 @@ type Fizz = OverrideProperties<Foo, {b: number; c: number}>
25
25
  */
26
26
  export type OverrideProperties<
27
27
  TOriginal,
28
- TOverride extends {[Key in keyof TOverride]: Key extends keyof TOriginal ? TOverride[Key] : never},
28
+ // This first bit where we use `Partial` is to enable autocomplete
29
+ // and the second bit with the mapped type is what enforces that we don't try
30
+ // to override properties that doesn't exist in the original type.
31
+ TOverride extends Partial<Record<keyof TOriginal, unknown>> & {
32
+ [Key in keyof TOverride]: Key extends keyof TOriginal
33
+ ? TOverride[Key]
34
+ : never;
35
+ },
29
36
  > = Merge<TOriginal, TOverride>;
@@ -0,0 +1,81 @@
1
+ import type {BuiltIns} from './internal';
2
+ import type {Merge} from './merge';
3
+
4
+ /**
5
+ Create a deep version of another type where all optional keys are set to also accept `undefined`.
6
+
7
+ Note: This is only needed when the [`exactOptionalPropertyTypes`](https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes) TSConfig setting is enabled.
8
+
9
+ Use-cases:
10
+ - When `exactOptionalPropertyTypes` is enabled, an object like `{a: undefined}` is not assignable to the type `{a?: number}`. You can use `UndefinedOnPartialDeep<{a?: number}>` to make it assignable.
11
+
12
+ @example
13
+ ```
14
+ import type {UndefinedOnPartialDeep} from 'type-fest';
15
+
16
+ interface Settings {
17
+ optionA: string;
18
+ optionB?: number;
19
+ subOption: {
20
+ subOptionA: boolean;
21
+ subOptionB?: boolean;
22
+ }
23
+ };
24
+
25
+ const testSettingsA: Settings = {
26
+ optionA: 'foo',
27
+ optionB: undefined, // TypeScript error if `exactOptionalPropertyTypes` is true.
28
+ subOption: {
29
+ subOptionA: true,
30
+ subOptionB: undefined, // TypeScript error if `exactOptionalPropertyTypes` is true
31
+ },
32
+ };
33
+
34
+ const testSettingsB: UndefinedOnPartialDeep<Settings> = {
35
+ optionA: 'foo',
36
+ optionB: undefined, // 👉 `optionB` can be set to undefined now.
37
+ subOption: {
38
+ subOptionA: true,
39
+ subOptionB: undefined, // 👉 `subOptionB` can be set to undefined now.
40
+ },
41
+ };
42
+ ```
43
+ */
44
+ export type UndefinedOnPartialDeep<T> =
45
+ // Handle built-in type and function
46
+ T extends BuiltIns | Function
47
+ ? T
48
+ // Handle tuple and array
49
+ : T extends readonly unknown[]
50
+ ? UndefinedOnPartialList<T>
51
+ // Handle map and readonly map
52
+ : T extends Map<infer K, infer V>
53
+ ? Map<K, UndefinedOnPartialDeep<V>>
54
+ : T extends ReadonlyMap<infer K, infer V>
55
+ ? ReadonlyMap<K, UndefinedOnPartialDeep<V>>
56
+ // Handle set and readonly set
57
+ : T extends Set<infer K>
58
+ ? Set<UndefinedOnPartialDeep<K>>
59
+ : T extends ReadonlySet<infer K>
60
+ ? ReadonlySet<UndefinedOnPartialDeep<K>>
61
+ // Handle object
62
+ : T extends Record<any, any>
63
+ ? {
64
+ [KeyType in keyof T]: undefined extends T[KeyType]
65
+ ? UndefinedOnPartialDeep<T[KeyType]> | undefined
66
+ : UndefinedOnPartialDeep<T[KeyType]>
67
+ }
68
+ : T; // If T is not builtins / function / array / map / set / object, return T
69
+
70
+ // Handle tuples and arrays
71
+ type UndefinedOnPartialList<T extends readonly unknown[]> = T extends []
72
+ ? []
73
+ : T extends [infer F, ...infer R]
74
+ ? [UndefinedOnPartialDeep<F>, ...UndefinedOnPartialDeep<R>]
75
+ : T extends readonly [infer F, ...infer R]
76
+ ? readonly [UndefinedOnPartialDeep<F>, ...UndefinedOnPartialDeep<R>]
77
+ : T extends Array<infer F>
78
+ ? Array<UndefinedOnPartialDeep<F>>
79
+ : T extends ReadonlyArray<infer F>
80
+ ? ReadonlyArray<UndefinedOnPartialDeep<F>>
81
+ : never;
@@ -56,5 +56,6 @@ export type UnionToIntersection<Union> = (
56
56
  // Infer the `Intersection` type since TypeScript represents the positional
57
57
  // arguments of unions of functions as an intersection of the union.
58
58
  ) extends ((mergedIntersection: infer Intersection) => void)
59
- ? Intersection
59
+ // The `& Union` is to allow indexing by the resulting type
60
+ ? Intersection & Union
60
61
  : never;