type-fest 4.20.1 → 4.22.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
@@ -64,6 +64,7 @@ export type {Simplify} from './source/simplify';
64
64
  export type {SimplifyDeep} from './source/simplify-deep';
65
65
  export type {Jsonify} from './source/jsonify';
66
66
  export type {Jsonifiable} from './source/jsonifiable';
67
+ export type {StructuredCloneable} from './source/structured-cloneable';
67
68
  export type {Schema} from './source/schema';
68
69
  export type {LiteralToPrimitive} from './source/literal-to-primitive';
69
70
  export type {LiteralToPrimitiveDeep} from './source/literal-to-primitive-deep';
@@ -121,6 +122,7 @@ export type {ArrayIndices} from './source/array-indices';
121
122
  export type {ArrayValues} from './source/array-values';
122
123
  export type {ArraySlice} from './source/array-slice';
123
124
  export type {ArraySplice} from './source/array-splice';
125
+ export type {ArrayTail} from './source/array-tail';
124
126
  export type {SetFieldType} from './source/set-field-type';
125
127
  export type {Paths} from './source/paths';
126
128
  export type {SharedUnionFieldsDeep} from './source/shared-union-fields-deep';
@@ -128,6 +130,8 @@ export type {IsNull} from './source/is-null';
128
130
  export type {IfNull} from './source/if-null';
129
131
  export type {And} from './source/and';
130
132
  export type {Or} from './source/or';
133
+ export type {NonEmptyTuple} from './source/non-empty-tuple';
134
+ export type {FindGlobalInstanceType, FindGlobalType} from './source/find-global-type';
131
135
 
132
136
  // Template literal types
133
137
  export type {CamelCase} from './source/camel-case';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-fest",
3
- "version": "4.20.1",
3
+ "version": "4.22.0",
4
4
  "description": "A collection of essential TypeScript types",
5
5
  "license": "(MIT OR CC0-1.0)",
6
6
  "repository": "sindresorhus/type-fest",
@@ -42,7 +42,7 @@
42
42
  "expect-type": "^0.19.0",
43
43
  "npm-run-all2": "^6.1.2",
44
44
  "tsd": "^0.31.0",
45
- "typescript": "~5.4.5",
45
+ "typescript": "~5.5.3",
46
46
  "xo": "^0.58.0"
47
47
  },
48
48
  "xo": {
package/readme.md CHANGED
@@ -167,7 +167,7 @@ Click the type names for complete docs.
167
167
  - [`LiteralToPrimitive`](source/literal-to-primitive.d.ts) - Convert a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) to the [primitive type](source/primitive.d.ts) it belongs to.
168
168
  - [`LiteralToPrimitiveDeep`](source/literal-to-primitive-deep.d.ts) - Like `LiteralToPrimitive` except it converts literal types inside an object or array deeply.
169
169
  - [`Stringified`](source/stringified.d.ts) - Create a type with the keys of the given type changed to `string` type.
170
- - [`IterableElement`](source/iterable-element.d.ts) - Get the element type of an `Iterable`/`AsyncIterable`. For example, an array or a generator.
170
+ - [`IterableElement`](source/iterable-element.d.ts) - Get the element type of an `Iterable`/`AsyncIterable`. For example, `Array`, `Set`, `Map`, generator, stream, etc.
171
171
  - [`Entry`](source/entry.d.ts) - Create a type that represents the type of an entry of a collection.
172
172
  - [`Entries`](source/entries.d.ts) - Create a type that represents the type of the entries of a collection.
173
173
  - [`SetReturnType`](source/set-return-type.d.ts) - Create a function type with a return type of your choice and the same parameters as the given function type.
@@ -194,6 +194,7 @@ Click the type names for complete docs.
194
194
  - [`ArrayIndices`](source/array-indices.d.ts) - Provides valid indices for a constant array or tuple.
195
195
  - [`ArrayValues`](source/array-values.d.ts) - Provides all values for a constant array or tuple.
196
196
  - [`ArraySplice`](source/array-splice.d.ts) - Creates a new array type by adding or removing elements at a specified index range in the original array.
197
+ - [`ArrayTail`](source/array-tail.d.ts) - Extracts the type of an array or tuple minus the first element.
197
198
  - [`SetFieldType`](source/set-field-type.d.ts) - Create a type that changes the type of the given keys.
198
199
  - [`Paths`](source/paths.d.ts) - Generate a union of all possible paths to properties in the given object.
199
200
  - [`SharedUnionFieldsDeep`](source/shared-union-fields-deep.d.ts) - Create a type with shared fields from a union of object types, deeply traversing nested structures.
@@ -201,6 +202,9 @@ Click the type names for complete docs.
201
202
  - [`DistributedPick`](source/distributed-pick.d.ts) - Picks keys from a type, distributing the operation over a union.
202
203
  - [`And`](source/and.d.ts) - Returns a boolean for whether two given types are both true.
203
204
  - [`Or`](source/or.d.ts) - Returns a boolean for whether either of two given types are true.
205
+ - [`NonEmptyTuple`](source/non-empty-tuple.d.ts) - Matches any non-empty tuple.
206
+ - [`FindGlobalType`](source/find-global-type.d.ts) - Tries to find the type of a global with the given name.
207
+ - [`FindGlobalInstanceType`](source/find-global-type.d.ts) - Tries to find one or more types from their globally-defined constructors.
204
208
 
205
209
  ### Type Guard
206
210
 
@@ -249,6 +253,10 @@ type ShouldBeNever = IfAny<'not any', 'not never', 'never'>;
249
253
  - [`JsonArray`](source/basic.d.ts) - Matches a JSON array.
250
254
  - [`JsonValue`](source/basic.d.ts) - Matches any valid JSON value.
251
255
 
256
+ ### Structured clone
257
+
258
+ - [`StructuredCloneable`](source/structured-cloneable.d.ts) - Matches a value that can be losslessly cloned using `structuredClone`.
259
+
252
260
  ### Async
253
261
 
254
262
  - [`Promisable`](source/promisable.d.ts) - Create a type that represents either the value or the value wrapped in `PromiseLike`.
@@ -343,11 +351,14 @@ type ShouldBeNever = IfAny<'not any', 'not never', 'never'>;
343
351
  - `PartialBy` - See [`SetOptional`](source/set-optional.d.ts)
344
352
  - `RecordDeep`- See [`Schema`](source/schema.d.ts)
345
353
  - `Mutable`- See [`Writable`](source/writable.d.ts)
346
- - `RequireOnlyOne` - See [`RequireExactlyOne`](source/require-exactly-one.d.ts)
354
+ - `RequireOnlyOne`, `OneOf` - See [`RequireExactlyOne`](source/require-exactly-one.d.ts)
347
355
  - `AtMostOne` - See [`RequireOneOrNone`](source/require-one-or-none.d.ts)
348
356
  - `AllKeys` - See [`KeysOfUnion`](source/keys-of-union.d.ts)
349
357
  - `Branded` - See [`Tagged`](source/opaque.d.ts)
350
358
  - `Opaque` - See [`Tagged`](source/opaque.d.ts)
359
+ - `SetElement` - See [`IterableElement`](source/iterable-element.d.ts)
360
+ - `SetEntry` - See [`IterableElement`](source/iterable-element.d.ts)
361
+ - `SetValues` - See [`IterableElement`](source/iterable-element.d.ts)
351
362
 
352
363
  ## Tips
353
364
 
@@ -3,7 +3,7 @@ import type {LessThanOrEqual} from './less-than-or-equal';
3
3
  import type {GreaterThanOrEqual} from './greater-than-or-equal';
4
4
  import type {GreaterThan} from './greater-than';
5
5
  import type {IsNegative} from './numeric';
6
- import type {Not, ArrayMin} from './internal';
6
+ import type {Not, TupleMin} from './internal';
7
7
  import type {IsEqual} from './is-equal';
8
8
  import type {And} from './and';
9
9
  import type {ArraySplice} from './array-splice';
@@ -95,7 +95,7 @@ type ArraySliceHelper<
95
95
  PositiveE extends number = IsNegative<End> extends true ? Sum<ArrayLength, End> : End,
96
96
  > = true extends [IsNegative<PositiveS>, LessThanOrEqual<PositiveE, PositiveS>, GreaterThanOrEqual<PositiveS, ArrayLength>][number]
97
97
  ? []
98
- : ArraySliceByPositiveIndex<Array_, ArrayMin<[PositiveS, ArrayLength]>, ArrayMin<[PositiveE, ArrayLength]>>;
98
+ : ArraySliceByPositiveIndex<Array_, TupleMin<[PositiveS, ArrayLength]>, TupleMin<[PositiveE, ArrayLength]>>;
99
99
 
100
100
  type ArraySliceByPositiveIndex<
101
101
  Array_ extends readonly unknown[],
@@ -0,0 +1,25 @@
1
+ import type {UnknownArrayOrTuple} from './internal';
2
+
3
+ /**
4
+ Extracts the type of an array or tuple minus the first element.
5
+
6
+ @example
7
+ ```
8
+ import type {ArrayTail} from 'type-fest';
9
+
10
+ declare const curry: <Arguments extends unknown[], Return>(
11
+ function_: (...arguments_: Arguments) => Return,
12
+ ...arguments_: ArrayTail<Arguments>
13
+ ) => (...arguments_: ArrayTail<Arguments>) => Return;
14
+
15
+ const add = (a: number, b: number) => a + b;
16
+
17
+ const add3 = curry(add, 3);
18
+
19
+ add3(4);
20
+ //=> 7
21
+ ```
22
+
23
+ @category Array
24
+ */
25
+ export type ArrayTail<TArray extends UnknownArrayOrTuple> = TArray extends readonly [unknown, ...infer Tail] ? Tail : [];
@@ -1,4 +1,5 @@
1
1
  import type {CamelCase, CamelCaseOptions} from './camel-case';
2
+ import type {NonRecursiveType} from './internal';
2
3
  import type {UnknownArray} from './unknown-array';
3
4
 
4
5
  /**
@@ -48,7 +49,7 @@ const result: CamelCasedPropertiesDeep<UserWithFriends> = {
48
49
  export type CamelCasedPropertiesDeep<
49
50
  Value,
50
51
  Options extends CamelCaseOptions = {preserveConsecutiveUppercase: true},
51
- > = Value extends Function
52
+ > = Value extends NonRecursiveType
52
53
  ? Value
53
54
  : Value extends UnknownArray
54
55
  ? CamelCasedPropertiesArrayDeep<Value>
@@ -1,4 +1,4 @@
1
- import type {UpperCaseCharacters, WordSeparators} from '../source/internal';
1
+ import type {UpperCaseCharacters, WordSeparators} from './internal';
2
2
 
3
3
  // Transforms a string that is fully uppercase into a fully lowercase version. Needed to add support for SCREAMING_SNAKE_CASE, see https://github.com/sindresorhus/type-fest/issues/385
4
4
  type UpperCaseToLowerCase<T extends string> = T extends Uppercase<T> ? Lowercase<T> : T;
package/source/exact.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type {ArrayElement, ObjectValue} from './internal';
2
- import type {Opaque, TagContainer} from './opaque';
3
2
  import type {IsEqual} from './is-equal';
4
3
  import type {KeysOfUnion} from './keys-of-union';
4
+ import type {IsUnknown} from './is-unknown';
5
+ import type {Primitive} from './primitive';
5
6
 
6
7
  /**
7
8
  Create a type from `ParameterType` and `InputType` and change keys exclusive to `InputType` to `never`.
@@ -52,12 +53,15 @@ onlyAcceptNameImproved(invalidInput); // Compilation error
52
53
  @category Utilities
53
54
  */
54
55
  export type Exact<ParameterType, InputType> =
55
- IsEqual<ParameterType, InputType> extends true ? ParameterType
56
- // Convert union of array to array of union: A[] & B[] => (A & B)[]
57
- : ParameterType extends unknown[] ? Array<Exact<ArrayElement<ParameterType>, ArrayElement<InputType>>>
58
- // In TypeScript, Array is a subtype of ReadonlyArray, so always test Array before ReadonlyArray.
59
- : ParameterType extends readonly unknown[] ? ReadonlyArray<Exact<ArrayElement<ParameterType>, ArrayElement<InputType>>>
60
- // Leave tagged types as-is. We could try to make the untagged part Exact, and just leave the tag as-is, but that seems to create instanitation excessively deep errors.
61
- : ParameterType extends TagContainer<unknown> ? ParameterType
62
- : ParameterType extends object ? ExactObject<ParameterType, InputType>
63
- : ParameterType;
56
+ // If the parameter is a primitive, return it as is immediately to avoid it being converted to a complex type
57
+ ParameterType extends Primitive ? ParameterType
58
+ // If the parameter is an unknown, return it as is immediately to avoid it being converted to a complex type
59
+ : IsUnknown<ParameterType> extends true ? unknown
60
+ // If the parameter is a Function, return it as is because this type is not capable of handling function, leave it to TypeScript
61
+ : ParameterType extends Function ? ParameterType
62
+ : IsEqual<ParameterType, InputType> extends true ? ParameterType
63
+ // Convert union of array to array of union: A[] & B[] => (A & B)[]
64
+ : ParameterType extends unknown[] ? Array<Exact<ArrayElement<ParameterType>, ArrayElement<InputType>>>
65
+ // In TypeScript, Array is a subtype of ReadonlyArray, so always test Array before ReadonlyArray.
66
+ : ParameterType extends readonly unknown[] ? ReadonlyArray<Exact<ArrayElement<ParameterType>, ArrayElement<InputType>>>
67
+ : ExactObject<ParameterType, InputType>;
@@ -0,0 +1,64 @@
1
+ /**
2
+ Tries to find the type of a global with the given name.
3
+
4
+ Limitations: Due to peculiarities with the behavior of `globalThis`, "globally defined" only includes `var` declarations in `declare global` blocks, not `let` or `const` declarations.
5
+
6
+ @example
7
+ ```
8
+ import type {FindGlobalType} from 'type-fest';
9
+
10
+ declare global {
11
+ const foo: number; // let and const don't work
12
+ var bar: string; // var works
13
+ }
14
+
15
+ type FooType = FindGlobalType<'foo'> //=> never (let/const don't work)
16
+ type BarType = FindGlobalType<'bar'> //=> string
17
+ type OtherType = FindGlobalType<'other'> //=> never (no global named 'other')
18
+ ```
19
+
20
+ @category Utilities
21
+ */
22
+ export type FindGlobalType<Name extends string> = typeof globalThis extends Record<Name, infer T> ? T : never;
23
+
24
+ /**
25
+ Tries to find one or more types from their globally-defined constructors.
26
+
27
+ Use-case: Conditionally referencing DOM types only when the DOM library present.
28
+
29
+ *Limitations:* Due to peculiarities with the behavior of `globalThis`, "globally defined" has a narrow definition in this case. Declaring a class in a `declare global` block won't work, instead you must declare its type using an interface and declare its constructor as a `var` (*not* `let`/`const`) inside the `declare global` block.
30
+
31
+ @example
32
+ ```
33
+ import type {FindGlobalInstanceType} from 'type-fest';
34
+
35
+ class Point {
36
+ constructor(public x: number, public y: number) {}
37
+ }
38
+
39
+ type PointLike = Point | FindGlobalInstanceType<'DOMPoint'>;
40
+ ```
41
+
42
+ @example
43
+ ```
44
+ import type {FindGlobalInstanceType} from 'type-fest';
45
+
46
+ declare global {
47
+ // Class syntax won't add the key to `globalThis`
48
+ class Foo {}
49
+
50
+ // interface + constructor style works
51
+ interface Bar {}
52
+ var Bar: new () => Bar; // Not let or const
53
+ }
54
+
55
+ type FindFoo = FindGlobalInstanceType<'Foo'>; // Doesn't work
56
+ type FindBar = FindGlobalInstanceType<'Bar'>; // Works
57
+ ```
58
+
59
+ @category Utilities
60
+ */
61
+ export type FindGlobalInstanceType<Name extends string> =
62
+ Name extends string
63
+ ? typeof globalThis extends Record<Name, abstract new (...arguments: any[]) => infer T> ? T : never
64
+ : never;
package/source/get.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type {StringDigit} from '../source/internal';
1
+ import type {StringDigit} from './internal';
2
2
  import type {Split} from './split';
3
3
  import type {StringKeyOf} from './string-key-of';
4
4
 
@@ -8,7 +8,7 @@ The numbers are created from the given `Start` (inclusive) parameter to the give
8
8
 
9
9
  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`.
10
10
 
11
- Note: `Start` or `End` must smaller than `1000`.
11
+ Note: `Start` or `End` must be non-negative and smaller than `1000`.
12
12
 
13
13
  Use-cases:
14
14
  1. This can be used to define a set of valid input/output values. for example:
@@ -0,0 +1,93 @@
1
+ import type {UnknownArray} from '../unknown-array';
2
+
3
+ /**
4
+ Infer the length of the given array `<T>`.
5
+
6
+ @link https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f
7
+ */
8
+ type ArrayLength<T extends readonly unknown[]> = T extends {readonly length: infer L} ? L : never;
9
+
10
+ /**
11
+ Matches any unknown array or tuple.
12
+ */
13
+ export type UnknownArrayOrTuple = readonly [...unknown[]];
14
+ // TODO: should unknown-array be updated?
15
+
16
+ /**
17
+ Extracts the type of the first element of an array or tuple.
18
+ */
19
+ export type FirstArrayElement<TArray extends UnknownArrayOrTuple> = TArray extends readonly [infer THead, ...unknown[]]
20
+ ? THead
21
+ : never;
22
+
23
+ /**
24
+ Extract the element of an array that also works for array union.
25
+
26
+ Returns `never` if T is not an array.
27
+
28
+ It creates a type-safe way to access the element type of `unknown` type.
29
+ */
30
+ export type ArrayElement<T> = T extends readonly unknown[] ? T[0] : never;
31
+
32
+ /**
33
+ Returns the static, fixed-length portion of the given array, excluding variable-length parts.
34
+
35
+ @example
36
+ ```
37
+ type A = [string, number, boolean, ...string[]];
38
+ type B = StaticPartOfArray<A>;
39
+ //=> [string, number, boolean]
40
+ ```
41
+ */
42
+ export type StaticPartOfArray<T extends UnknownArray, Result extends UnknownArray = []> =
43
+ T extends unknown
44
+ ? number extends T['length'] ?
45
+ T extends readonly [infer U, ...infer V]
46
+ ? StaticPartOfArray<V, [...Result, U]>
47
+ : Result
48
+ : T
49
+ : never; // Should never happen
50
+
51
+ /**
52
+ Returns the variable, non-fixed-length portion of the given array, excluding static-length parts.
53
+
54
+ @example
55
+ ```
56
+ type A = [string, number, boolean, ...string[]];
57
+ type B = VariablePartOfArray<A>;
58
+ //=> string[]
59
+ ```
60
+ */
61
+ export type VariablePartOfArray<T extends UnknownArray> =
62
+ T extends unknown
63
+ ? T extends readonly [...StaticPartOfArray<T>, ...infer U]
64
+ ? U
65
+ : []
66
+ : never; // Should never happen
67
+
68
+ /**
69
+ Set the given array to readonly if `IsReadonly` is `true`, otherwise set the given array to normal, then return the result.
70
+
71
+ @example
72
+ ```
73
+ type ReadonlyArray = readonly string[];
74
+ type NormalArray = string[];
75
+
76
+ type ReadonlyResult = SetArrayAccess<NormalArray, true>;
77
+ //=> readonly string[]
78
+
79
+ type NormalResult = SetArrayAccess<ReadonlyArray, false>;
80
+ //=> string[]
81
+ ```
82
+ */
83
+ export type SetArrayAccess<T extends UnknownArray, IsReadonly extends boolean> =
84
+ T extends readonly [...infer U] ?
85
+ IsReadonly extends true
86
+ ? readonly [...U]
87
+ : [...U]
88
+ : T;
89
+
90
+ /**
91
+ Returns whether the given array `T` is readonly.
92
+ */
93
+ export type IsArrayReadonly<T extends UnknownArray> = T extends unknown[] ? false : true;
@@ -0,0 +1,33 @@
1
+ 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';
2
+
3
+ export type StringDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
4
+
5
+ export type Whitespace =
6
+ | '\u{9}' // '\t'
7
+ | '\u{A}' // '\n'
8
+ | '\u{B}' // '\v'
9
+ | '\u{C}' // '\f'
10
+ | '\u{D}' // '\r'
11
+ | '\u{20}' // ' '
12
+ | '\u{85}'
13
+ | '\u{A0}'
14
+ | '\u{1680}'
15
+ | '\u{2000}'
16
+ | '\u{2001}'
17
+ | '\u{2002}'
18
+ | '\u{2003}'
19
+ | '\u{2004}'
20
+ | '\u{2005}'
21
+ | '\u{2006}'
22
+ | '\u{2007}'
23
+ | '\u{2008}'
24
+ | '\u{2009}'
25
+ | '\u{200A}'
26
+ | '\u{2028}'
27
+ | '\u{2029}'
28
+ | '\u{202F}'
29
+ | '\u{205F}'
30
+ | '\u{3000}'
31
+ | '\u{FEFF}';
32
+
33
+ export type WordSeparators = '-' | '_' | Whitespace;
@@ -0,0 +1,8 @@
1
+ export type * from './array';
2
+ export type * from './characters';
3
+ export type * from './keys';
4
+ export type * from './numeric';
5
+ export type * from './object';
6
+ export type * from './string';
7
+ export type * from './tuple';
8
+ export type * from './type';
@@ -0,0 +1,97 @@
1
+ import type {IsAny} from '../is-any';
2
+ import type {IsLiteral} from '../is-literal';
3
+ import type {ToString} from './string';
4
+
5
+ // Returns `never` if the key or property is not jsonable without testing whether the property is required or optional otherwise return the key.
6
+ type BaseKeyFilter<Type, Key extends keyof Type> = Key extends symbol
7
+ ? never
8
+ : Type[Key] extends symbol
9
+ ? never
10
+ /*
11
+ To prevent a problem where an object with only a `name` property is incorrectly treated as assignable to a function, we first check if the property is a record.
12
+ This check is necessary, because without it, if we don't verify whether the property is a record, an object with a type of `{name: any}` would return `never` due to its potential assignability to a function.
13
+ See: https://github.com/sindresorhus/type-fest/issues/657
14
+ */
15
+ : Type[Key] extends Record<string, unknown>
16
+ ? Key
17
+ : [(...arguments_: any[]) => any] extends [Type[Key]]
18
+ ? never
19
+ : Key;
20
+
21
+ /**
22
+ Returns the required keys.
23
+ */
24
+ type FilterDefinedKeys<T extends object> = Exclude<
25
+ {
26
+ [Key in keyof T]: IsAny<T[Key]> extends true
27
+ ? Key
28
+ : undefined extends T[Key]
29
+ ? never
30
+ : T[Key] extends undefined
31
+ ? never
32
+ : BaseKeyFilter<T, Key>;
33
+ }[keyof T],
34
+ undefined
35
+ >;
36
+
37
+ /**
38
+ Returns the optional keys.
39
+ */
40
+ type FilterOptionalKeys<T extends object> = Exclude<
41
+ {
42
+ [Key in keyof T]: IsAny<T[Key]> extends true
43
+ ? never
44
+ : undefined extends T[Key]
45
+ ? T[Key] extends undefined
46
+ ? never
47
+ : BaseKeyFilter<T, Key>
48
+ : never;
49
+ }[keyof T],
50
+ undefined
51
+ >;
52
+
53
+ /**
54
+ Disallows any of the given keys.
55
+ */
56
+ export type RequireNone<KeysType extends PropertyKey> = Partial<Record<KeysType, never>>;
57
+
58
+ /**
59
+ Utility type to retrieve only literal keys from type.
60
+ */
61
+ export type LiteralKeyOf<T> = keyof {[K in keyof T as IsLiteral<K> extends true ? K : never]-?: never};
62
+
63
+ /**
64
+ Get the exact version of the given `Key` in the given object `T`.
65
+
66
+ Use-case: You known that a number key (e.g. 10) is in an object, but you don't know how it is defined in the object, as a string or as a number (e.g. 10 or '10'). You can use this type to get the exact version of the key. See the example.
67
+
68
+ @example
69
+ ```
70
+ type Object = {
71
+ 0: number;
72
+ '1': string;
73
+ };
74
+
75
+ type Key1 = ExactKey<Object, '0'>;
76
+ //=> 0
77
+ type Key2 = ExactKey<Object, 0>;
78
+ //=> 0
79
+
80
+ type Key3 = ExactKey<Object, '1'>;
81
+ //=> '1'
82
+ type Key4 = ExactKey<Object, 1>;
83
+ //=> '1'
84
+ ```
85
+
86
+ @category Object
87
+ */
88
+ export type ExactKey<T extends object, Key extends PropertyKey> =
89
+ Key extends keyof T
90
+ ? Key
91
+ : ToString<Key> extends keyof T
92
+ ? ToString<Key>
93
+ : Key extends `${infer NumberKey extends number}`
94
+ ? NumberKey extends keyof T
95
+ ? NumberKey
96
+ : never
97
+ : never;
@@ -0,0 +1,64 @@
1
+ import type {IsNever} from '../is-never';
2
+ import type {UnknownArray} from '../unknown-array';
3
+ import type {StringToNumber} from './string';
4
+
5
+ /**
6
+ Returns the absolute value of a given value.
7
+
8
+ @example
9
+ ```
10
+ NumberAbsolute<-1>;
11
+ //=> 1
12
+
13
+ NumberAbsolute<1>;
14
+ //=> 1
15
+
16
+ NumberAbsolute<NegativeInfinity>
17
+ //=> PositiveInfinity
18
+ ```
19
+ */
20
+ export type NumberAbsolute<N extends number> = `${N}` extends `-${infer StringPositiveN}` ? StringToNumber<StringPositiveN> : N;
21
+
22
+ /**
23
+ Returns the minimum number in the given union of numbers.
24
+
25
+ Note: Just supports numbers from 0 to 999.
26
+
27
+ @example
28
+ ```
29
+ type A = UnionMin<3 | 1 | 2>;
30
+ //=> 1
31
+ ```
32
+ */
33
+ export type UnionMin<N extends number> = InternalUnionMin<N>;
34
+
35
+ /**
36
+ The actual implementation of `UnionMin`. It's private because it has some arguments that don't need to be exposed.
37
+ */
38
+ type InternalUnionMin<N extends number, T extends UnknownArray = []> =
39
+ T['length'] extends N
40
+ ? T['length']
41
+ : InternalUnionMin<N, [...T, unknown]>;
42
+
43
+ /**
44
+ Returns the maximum number in the given union of numbers.
45
+
46
+ Note: Just supports numbers from 0 to 999.
47
+
48
+ @example
49
+ ```
50
+ type A = UnionMax<1 | 3 | 2>;
51
+ //=> 3
52
+ ```
53
+ */
54
+ export type UnionMax<N extends number> = InternalUnionMax<N>;
55
+
56
+ /**
57
+ The actual implementation of `UnionMax`. It's private because it has some arguments that don't need to be exposed.
58
+ */
59
+ type InternalUnionMax<N extends number, T extends UnknownArray = []> =
60
+ IsNever<N> extends true
61
+ ? T['length']
62
+ : T['length'] extends N
63
+ ? InternalUnionMax<Exclude<N, T['length']>, T>
64
+ : InternalUnionMax<N, [...T, unknown]>;
@@ -0,0 +1,82 @@
1
+ import type {Simplify} from '../simplify';
2
+ import type {UnknownArray} from '../unknown-array';
3
+ import type {FilterDefinedKeys, FilterOptionalKeys} from './keys';
4
+ import type {NonRecursiveType} from './type';
5
+ import type {ToString} from './string';
6
+
7
+ /**
8
+ Create an object type with the given key `<Key>` and value `<Value>`.
9
+
10
+ It will copy the prefix and optional status of the same key from the given object `CopiedFrom` into the result.
11
+
12
+ @example
13
+ ```
14
+ type A = BuildObject<'a', string>;
15
+ //=> {a: string}
16
+
17
+ // Copy `readonly` and `?` from the key `a` of `{readonly a?: any}`
18
+ type B = BuildObject<'a', string, {readonly a?: any}>;
19
+ //=> {readonly a?: string}
20
+ ```
21
+ */
22
+ export type BuildObject<Key extends PropertyKey, Value, CopiedFrom extends object = {}> =
23
+ Key extends keyof CopiedFrom
24
+ ? Pick<{[_ in keyof CopiedFrom]: Value}, Key>
25
+ : Key extends `${infer NumberKey extends number}`
26
+ ? NumberKey extends keyof CopiedFrom
27
+ ? Pick<{[_ in keyof CopiedFrom]: Value}, NumberKey>
28
+ : {[_ in Key]: Value}
29
+ : {[_ in Key]: Value};
30
+
31
+ /**
32
+ Returns a boolean for whether the given type is a plain key-value object.
33
+ */
34
+ export type IsPlainObject<T> =
35
+ T extends NonRecursiveType | UnknownArray | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
36
+ ? false
37
+ : T extends object
38
+ ? true
39
+ : false;
40
+
41
+ /**
42
+ Extract the object field type if T is an object and K is a key of T, return `never` otherwise.
43
+
44
+ It creates a type-safe way to access the member type of `unknown` type.
45
+ */
46
+ export type ObjectValue<T, K> =
47
+ K extends keyof T
48
+ ? T[K]
49
+ : ToString<K> extends keyof T
50
+ ? T[ToString<K>]
51
+ : K extends `${infer NumberK extends number}`
52
+ ? NumberK extends keyof T
53
+ ? T[NumberK]
54
+ : never
55
+ : never;
56
+
57
+ /**
58
+ For an object T, if it has any properties that are a union with `undefined`, make those into optional properties instead.
59
+
60
+ @example
61
+ ```
62
+ type User = {
63
+ firstName: string;
64
+ lastName: string | undefined;
65
+ };
66
+
67
+ type OptionalizedUser = UndefinedToOptional<User>;
68
+ //=> {
69
+ // firstName: string;
70
+ // lastName?: string;
71
+ // }
72
+ ```
73
+ */
74
+ export type UndefinedToOptional<T extends object> = Simplify<
75
+ {
76
+ // Property is not a union with `undefined`, keep it as-is.
77
+ [Key in keyof Pick<T, FilterDefinedKeys<T>>]: T[Key];
78
+ } & {
79
+ // Property _is_ a union with defined value. Set as optional (via `?`) and remove `undefined` from the union.
80
+ [Key in keyof Pick<T, FilterOptionalKeys<T>>]?: Exclude<T[Key], undefined>;
81
+ }
82
+ >;