type-fest 4.40.1 → 4.41.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
@@ -47,6 +47,7 @@ export type {SetReadonly} from './source/set-readonly';
47
47
  export type {SetRequired} from './source/set-required';
48
48
  export type {SetRequiredDeep} from './source/set-required-deep';
49
49
  export type {SetNonNullable} from './source/set-non-nullable';
50
+ export type {SetNonNullableDeep} from './source/set-non-nullable-deep';
50
51
  export type {ValueOf} from './source/value-of';
51
52
  export type {AsyncReturnType} from './source/async-return-type';
52
53
  export type {ConditionalExcept} from './source/conditional-except';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-fest",
3
- "version": "4.40.1",
3
+ "version": "4.41.0",
4
4
  "description": "A collection of essential TypeScript types",
5
5
  "license": "(MIT OR CC0-1.0)",
6
6
  "repository": "sindresorhus/type-fest",
package/readme.md CHANGED
@@ -151,6 +151,7 @@ Click the type names for complete docs.
151
151
  - [`SetRequired`](source/set-required.d.ts) - Create a type that makes the given keys required.
152
152
  - [`SetRequiredDeep`](source/set-required-deep.d.ts) - Like `SetRequired` except it selects the keys deeply.
153
153
  - [`SetNonNullable`](source/set-non-nullable.d.ts) - Create a type that makes the given keys non-nullable.
154
+ - [`SetNonNullableDeep`](source/set-non-nullable-deep.d.ts) - Create a type that makes the specified keys non-nullable (removes `null` and `undefined`), supports deeply nested key paths, and leaves all other keys unchanged.
154
155
  - [`ValueOf`](source/value-of.d.ts) - Create a union of the given object's values, and optionally specify which keys to get the values from.
155
156
  - [`ConditionalKeys`](source/conditional-keys.d.ts) - Extract keys from a shape where values extend the given `Condition` type.
156
157
  - [`ConditionalPick`](source/conditional-pick.d.ts) - Like `Pick` except it selects properties from a shape where the values extend the given `Condition` type.
@@ -21,31 +21,36 @@ GreaterThan<1, 5>;
21
21
  //=> false
22
22
  ```
23
23
  */
24
- export type GreaterThan<A extends number, B extends number> = number extends A | B
25
- ? never
26
- : [
27
- IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>,
28
- IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity>,
29
- ] extends infer R extends [boolean, boolean, boolean, boolean]
30
- ? Or<
31
- And<IsEqual<R[0], true>, IsEqual<R[2], false>>,
32
- And<IsEqual<R[3], true>, IsEqual<R[1], false>>
33
- > extends true
34
- ? true
35
- : Or<
36
- And<IsEqual<R[1], true>, IsEqual<R[3], false>>,
37
- And<IsEqual<R[2], true>, IsEqual<R[0], false>>
38
- > extends true
39
- ? false
40
- : true extends R[number]
41
- ? false
42
- : [IsNegative<A>, IsNegative<B>] extends infer R extends [boolean, boolean]
43
- ? [true, false] extends R
24
+ export type GreaterThan<A extends number, B extends number> =
25
+ A extends number // For distributing `A`
26
+ ? B extends number // For distributing `B`
27
+ ? number extends A | B
28
+ ? never
29
+ : [
30
+ IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>,
31
+ IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity>,
32
+ ] extends infer R extends [boolean, boolean, boolean, boolean]
33
+ ? Or<
34
+ And<IsEqual<R[0], true>, IsEqual<R[2], false>>,
35
+ And<IsEqual<R[3], true>, IsEqual<R[1], false>>
36
+ > extends true
37
+ ? true
38
+ : Or<
39
+ And<IsEqual<R[1], true>, IsEqual<R[3], false>>,
40
+ And<IsEqual<R[2], true>, IsEqual<R[0], false>>
41
+ > extends true
44
42
  ? false
45
- : [false, true] extends R
46
- ? true
47
- : [false, false] extends R
48
- ? PositiveNumericStringGt<`${A}`, `${B}`>
49
- : PositiveNumericStringGt<`${NumberAbsolute<B>}`, `${NumberAbsolute<A>}`>
50
- : never
51
- : never;
43
+ : true extends R[number]
44
+ ? false
45
+ : [IsNegative<A>, IsNegative<B>] extends infer R extends [boolean, boolean]
46
+ ? [true, false] extends R
47
+ ? false
48
+ : [false, true] extends R
49
+ ? true
50
+ : [false, false] extends R
51
+ ? PositiveNumericStringGt<`${A}`, `${B}`>
52
+ : PositiveNumericStringGt<`${NumberAbsolute<B>}`, `${NumberAbsolute<A>}`>
53
+ : never
54
+ : never
55
+ : never // Should never happen
56
+ : never; // Should never happen
@@ -1,3 +1,4 @@
1
+ import type {IsAny} from '../is-any';
1
2
  import type {IsNever} from '../is-never';
2
3
  import type {Primitive} from '../primitive';
3
4
 
@@ -111,3 +112,28 @@ type InternalIsUnion<T, U = T> =
111
112
  ? boolean extends Result ? true
112
113
  : Result
113
114
  : never; // Should never happen
115
+
116
+ /**
117
+ An if-else-like type that resolves depending on whether the given type is `any` or `never`.
118
+
119
+ @example
120
+ ```
121
+ // When `T` is a NOT `any` or `never` (like `string`) => Returns `IfNotAnyOrNever` branch
122
+ type A = IfNotAnyOrNever<string, 'VALID', 'IS_ANY', 'IS_NEVER'>;
123
+ //=> 'VALID'
124
+
125
+ // When `T` is `any` => Returns `IfAny` branch
126
+ type B = IfNotAnyOrNever<any, 'VALID', 'IS_ANY', 'IS_NEVER'>;
127
+ //=> 'IS_ANY'
128
+
129
+ // When `T` is `never` => Returns `IfNever` branch
130
+ type C = IfNotAnyOrNever<never, 'VALID', 'IS_ANY', 'IS_NEVER'>;
131
+ //=> 'IS_NEVER'
132
+ ```
133
+ */
134
+ export type IfNotAnyOrNever<T, IfNotAnyOrNever, IfAny = any, IfNever = never> =
135
+ IsAny<T> extends true
136
+ ? IfAny
137
+ : IsNever<T> extends true
138
+ ? IfNever
139
+ : IfNotAnyOrNever;
@@ -1,5 +1,3 @@
1
- import type {Zero} from './numeric';
2
-
3
1
  /**
4
2
  Returns a boolean for whether the given number is a float, like `1.5` or `-1.5`.
5
3
 
@@ -19,4 +19,8 @@ LessThan<1, 5>;
19
19
  */
20
20
  export type LessThan<A extends number, B extends number> = number extends A | B
21
21
  ? never
22
- : GreaterThanOrEqual<A, B> extends true ? false : true;
22
+ : GreaterThanOrEqual<A, B> extends infer Result
23
+ ? Result extends true
24
+ ? false
25
+ : true
26
+ : never; // Should never happen
@@ -1,4 +1,6 @@
1
- import type {RequireNone} from './internal';
1
+ import type {IfAny} from './if-any';
2
+ import type {IfNever} from './if-never';
3
+ import type {IfNotAnyOrNever, RequireNone} from './internal';
2
4
 
3
5
  /**
4
6
  Requires all of the keys in the given object.
@@ -36,7 +38,14 @@ const responder2: RequireAllOrNone<Responder, 'text' | 'json'> = {
36
38
 
37
39
  @category Object
38
40
  */
39
- export type RequireAllOrNone<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> = (
41
+ export type RequireAllOrNone<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
42
+ IfNotAnyOrNever<ObjectType,
43
+ IfNever<KeysType,
44
+ ObjectType,
45
+ _RequireAllOrNone<ObjectType, IfAny<KeysType, keyof ObjectType, KeysType>>
46
+ >>;
47
+
48
+ type _RequireAllOrNone<ObjectType, KeysType extends keyof ObjectType> = (
40
49
  | RequireAll<ObjectType, KeysType>
41
50
  | RequireNone<KeysType>
42
51
  ) & Omit<ObjectType, KeysType>; // The rest of the keys.
@@ -1,4 +1,7 @@
1
1
  import type {Except} from './except';
2
+ import type {IfAny} from './if-any';
3
+ import type {IfNever} from './if-never';
4
+ import type {IfNotAnyOrNever} from './internal';
2
5
 
3
6
  /**
4
7
  Create a type that requires at least one of the given keys. The remaining keys are kept as is.
@@ -24,6 +27,16 @@ const responder: RequireAtLeastOne<Responder, 'text' | 'json'> = {
24
27
  export type RequireAtLeastOne<
25
28
  ObjectType,
26
29
  KeysType extends keyof ObjectType = keyof ObjectType,
30
+ > =
31
+ IfNotAnyOrNever<ObjectType,
32
+ IfNever<KeysType,
33
+ never,
34
+ _RequireAtLeastOne<ObjectType, IfAny<KeysType, keyof ObjectType, KeysType>>
35
+ >>;
36
+
37
+ type _RequireAtLeastOne<
38
+ ObjectType,
39
+ KeysType extends keyof ObjectType,
27
40
  > = {
28
41
  // For each `Key` in `KeysType` make a mapped type:
29
42
  [Key in KeysType]-?: Required<Pick<ObjectType, Key>> & // 1. Make `Key`'s type required
@@ -1,3 +1,7 @@
1
+ import type {IfAny} from './if-any';
2
+ import type {IfNever} from './if-never';
3
+ import type {IfNotAnyOrNever} from './internal';
4
+
1
5
  /**
2
6
  Create a type that requires exactly one of the given keys and disallows more. The remaining keys are kept as is.
3
7
 
@@ -28,6 +32,13 @@ const responder: RequireExactlyOne<Responder, 'text' | 'json'> = {
28
32
  @category Object
29
33
  */
30
34
  export type RequireExactlyOne<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
35
+ IfNotAnyOrNever<ObjectType,
36
+ IfNever<KeysType,
37
+ never,
38
+ _RequireExactlyOne<ObjectType, IfAny<KeysType, keyof ObjectType, KeysType>>
39
+ >>;
40
+
41
+ type _RequireExactlyOne<ObjectType, KeysType extends keyof ObjectType> =
31
42
  {[Key in KeysType]: (
32
43
  Required<Pick<ObjectType, Key>> &
33
44
  Partial<Record<Exclude<KeysType, Key>, never>>
@@ -1,5 +1,7 @@
1
1
  import type {RequireExactlyOne} from './require-exactly-one';
2
- import type {RequireNone} from './internal';
2
+ import type {IfNotAnyOrNever, RequireNone} from './internal';
3
+ import type {IfNever} from './if-never';
4
+ import type {IfAny} from './if-any';
3
5
 
4
6
  /**
5
7
  Create a type that requires exactly one of the given keys and disallows more, or none of the given keys. The remaining keys are kept as is.
@@ -31,7 +33,14 @@ const responder3: Responder = {
31
33
 
32
34
  @category Object
33
35
  */
34
- export type RequireOneOrNone<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> = (
36
+ export type RequireOneOrNone<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
37
+ IfNotAnyOrNever<ObjectType,
38
+ IfNever<KeysType,
39
+ ObjectType,
40
+ _RequireOneOrNone<ObjectType, IfAny<KeysType, keyof ObjectType, KeysType>>
41
+ >>;
42
+
43
+ type _RequireOneOrNone<ObjectType, KeysType extends keyof ObjectType> = (
35
44
  | RequireExactlyOne<ObjectType, KeysType>
36
45
  | RequireNone<KeysType>
37
46
  ) & Omit<ObjectType, KeysType>; // Ignore unspecified keys.
@@ -0,0 +1,83 @@
1
+ import type {NonRecursiveType, StringToNumber} from './internal';
2
+ import type {Paths} from './paths';
3
+ import type {SetNonNullable} from './set-non-nullable';
4
+ import type {Simplify} from './simplify';
5
+ import type {UnionToTuple} from './union-to-tuple';
6
+ import type {UnknownArray} from './unknown-array';
7
+
8
+ /**
9
+ Create a type that makes the specified keys non-nullable (removes `null` and `undefined`), supports deeply nested key paths, and leaves all other keys unchanged.
10
+
11
+ NOTE: Optional modifiers (`?`) are not removed from properties. For example, `SetNonNullableDeep<{foo?: string | null | undefined}, 'foo'>` will result in `{foo?: string}`.
12
+
13
+ @example
14
+ ```
15
+ import type {SetNonNullableDeep} from 'type-fest';
16
+
17
+ type User = {
18
+ name: string;
19
+ address: {
20
+ city: string | undefined;
21
+ street?: string | null;
22
+ };
23
+ contact: {
24
+ email?: string | null | undefined;
25
+ phone: string | undefined;
26
+ };
27
+ };
28
+
29
+ type UpdatedUser = SetNonNullableDeep<User, 'address.street' | 'contact.email' | 'contact.phone'>;
30
+ //=> {
31
+ // name: string;
32
+ // address: {
33
+ // city: string | undefined;
34
+ // street?: string;
35
+ // };
36
+ // contact: {
37
+ // email?: string;
38
+ // phone: string;
39
+ // };
40
+ // };
41
+ ```
42
+
43
+ @example
44
+ ```
45
+ import type {SetNonNullableDeep} from 'type-fest';
46
+
47
+ // Set specific indices in an array to be non-nullable.
48
+ type ArrayExample1 = SetNonNullableDeep<{a: [number | null, number | null, number | undefined]}, 'a.1' | 'a.2'>;
49
+ //=> {a: [number | null, number, number]}
50
+
51
+ // Optional modifier (`?`) is not removed.
52
+ type ArrayExample2 = SetNonNullableDeep<{a: [(number | null)?, (number | null)?]}, 'a.1'>;
53
+ //=> {a: [(number | null)?, number?]}
54
+ ```
55
+
56
+ @category Object
57
+ */
58
+ export type SetNonNullableDeep<BaseType, KeyPaths extends Paths<BaseType>> =
59
+ SetNonNullableDeepHelper<BaseType, UnionToTuple<KeyPaths>>;
60
+
61
+ /**
62
+ Internal helper for {@link SetNonNullableDeep}.
63
+
64
+ Recursively transforms the `BaseType` by applying {@link SetNonNullableDeepSinglePath} for each path in `KeyPathsTuple`.
65
+ */
66
+ type SetNonNullableDeepHelper<BaseType, KeyPathsTuple extends UnknownArray> =
67
+ KeyPathsTuple extends [infer KeyPath, ...infer RestPaths]
68
+ ? SetNonNullableDeepHelper<SetNonNullableDeepSinglePath<BaseType, KeyPath>, RestPaths>
69
+ : BaseType;
70
+
71
+ /**
72
+ Makes a single path non-nullable in `BaseType`.
73
+ */
74
+ type SetNonNullableDeepSinglePath<BaseType, KeyPath> =
75
+ BaseType extends NonRecursiveType | ReadonlySet<unknown> | ReadonlyMap<unknown, unknown> // Also distributes `BaseType`
76
+ ? BaseType
77
+ : KeyPath extends `${infer Property}.${infer RestPath}`
78
+ ? {
79
+ [Key in keyof BaseType]: Property extends `${Key & (string | number)}`
80
+ ? SetNonNullableDeepSinglePath<BaseType[Key], RestPath>
81
+ : BaseType[Key];
82
+ }
83
+ : Simplify<SetNonNullable<BaseType, (KeyPath | StringToNumber<KeyPath & string>) & keyof BaseType>>;
@@ -1,6 +1,5 @@
1
1
  import type {Except} from './except';
2
2
  import type {HomomorphicPick} from './internal';
3
- import type {KeysOfUnion} from './keys-of-union';
4
3
  import type {Simplify} from './simplify';
5
4
 
6
5
  /**
@@ -1,6 +1,5 @@
1
1
  import type {Except} from './except';
2
2
  import type {HomomorphicPick} from './internal';
3
- import type {KeysOfUnion} from './keys-of-union';
4
3
  import type {Simplify} from './simplify';
5
4
 
6
5
  /**
@@ -1,6 +1,5 @@
1
1
  import type {Except} from './except';
2
2
  import type {HomomorphicPick, IfArrayReadonly} from './internal';
3
- import type {KeysOfUnion} from './keys-of-union';
4
3
  import type {OptionalKeysOf} from './optional-keys-of';
5
4
  import type {Simplify} from './simplify';
6
5
  import type {UnknownArray} from './unknown-array';
@@ -1,4 +1,4 @@
1
- import type {NonRecursiveType, UnionMin, UnionMax, TupleLength, StaticPartOfArray, VariablePartOfArray, IsUnion, IsArrayReadonly, SetArrayAccess, ApplyDefaultOptions} from './internal';
1
+ import type {NonRecursiveType, UnionMin, UnionMax, TupleLength, StaticPartOfArray, VariablePartOfArray, IsArrayReadonly, SetArrayAccess, ApplyDefaultOptions} from './internal';
2
2
  import type {IsNever} from './is-never';
3
3
  import type {UnknownArray} from './unknown-array';
4
4