@depup/type-fest 5.4.4-depup.0 → 5.9.0-depup.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/README.md +2 -2
- package/changes.json +5 -0
- package/index.d.ts +23 -8
- package/package.json +17 -11
- package/readme.md +98 -64
- package/source/absolute.d.ts +52 -0
- package/source/all-extend.d.ts +8 -7
- package/source/all-union-fields.d.ts +18 -18
- package/source/and-all.d.ts +76 -0
- package/source/and.d.ts +4 -3
- package/source/array-length.d.ts +36 -0
- package/source/array-reverse.d.ts +4 -3
- package/source/array-splice.d.ts +26 -26
- package/source/array-tail.d.ts +4 -4
- package/source/camel-case.d.ts +38 -5
- package/source/camel-cased-properties-deep.d.ts +11 -4
- package/source/camel-cased-properties.d.ts +5 -1
- package/source/conditional-keys.d.ts +1 -1
- package/source/conditional-pick-deep.d.ts +5 -3
- package/source/conditional-pick.d.ts +6 -4
- package/source/delimiter-case.d.ts +11 -9
- package/source/delimiter-cased-properties-deep.d.ts +8 -1
- package/source/delimiter-cased-properties.d.ts +5 -1
- package/source/empty-object.d.ts +1 -1
- package/source/entries.d.ts +1 -1
- package/source/entry.d.ts +1 -1
- package/source/exclude-exactly.d.ts +57 -0
- package/source/exclude-rest-element.d.ts +4 -4
- package/source/exclusify-union.d.ts +4 -4
- package/source/extends-strict.d.ts +129 -22
- package/source/extract-exactly.d.ts +56 -0
- package/source/get.d.ts +1 -1
- package/source/greater-than-or-equal.d.ts +34 -1
- package/source/greater-than.d.ts +37 -3
- package/source/has-optional-keys.d.ts +1 -1
- package/source/has-readonly-keys.d.ts +1 -1
- package/source/has-required-keys.d.ts +1 -1
- package/source/has-writable-keys.d.ts +1 -1
- package/source/int-closed-range.d.ts +1 -3
- package/source/int-range.d.ts +3 -5
- package/source/internal/array.d.ts +8 -15
- package/source/internal/keys.d.ts +9 -9
- package/source/internal/numeric.d.ts +19 -27
- package/source/internal/object.d.ts +44 -6
- package/source/internal/string.d.ts +1 -76
- package/source/internal/tuple.d.ts +3 -3
- package/source/internal/type.d.ts +16 -9
- package/source/is-boolean-literal.d.ts +39 -0
- package/source/is-equal.d.ts +0 -1
- package/source/is-integer.d.ts +8 -8
- package/source/is-literal.d.ts +43 -267
- package/source/is-numeric-literal.d.ts +50 -0
- package/source/is-string-literal.d.ts +72 -0
- package/source/is-symbol-literal.d.ts +39 -0
- package/source/is-union.d.ts +12 -12
- package/source/iterable-element.d.ts +5 -5
- package/source/jsonify.d.ts +5 -9
- package/source/kebab-case.d.ts +1 -0
- package/source/kebab-cased-properties-deep.d.ts +7 -0
- package/source/kebab-cased-properties.d.ts +5 -1
- package/source/keys-of-union.d.ts +2 -2
- package/source/last-array-element.d.ts +66 -13
- package/source/less-than-or-equal.d.ts +40 -4
- package/source/less-than.d.ts +35 -3
- package/source/literal-to-primitive.d.ts +1 -1
- package/source/literal-union.d.ts +1 -1
- package/source/merge-exclusive.d.ts +3 -3
- package/source/merge.d.ts +25 -0
- package/source/multidimensional-array.d.ts +1 -1
- package/source/multidimensional-readonly-array.d.ts +1 -1
- package/source/non-nullable-deep.d.ts +102 -0
- package/source/numeric.d.ts +3 -3
- package/source/object-merge.d.ts +21 -16
- package/source/omit-deep.d.ts +22 -23
- package/source/optional.d.ts +31 -0
- package/source/or-all.d.ts +73 -0
- package/source/or.d.ts +4 -11
- package/source/package-json.d.ts +7 -7
- package/source/partial-deep.d.ts +3 -1
- package/source/pascal-case.d.ts +1 -0
- package/source/pascal-cased-properties-deep.d.ts +7 -0
- package/source/pascal-cased-properties.d.ts +5 -1
- package/source/pick-deep.d.ts +8 -21
- package/source/readonly-deep.d.ts +5 -3
- package/source/remove-prefix.d.ts +16 -34
- package/source/remove-suffix.d.ts +114 -0
- package/source/rename-keys.d.ts +163 -0
- package/source/replace.d.ts +2 -2
- package/source/require-all-or-none.d.ts +5 -5
- package/source/require-at-least-one.d.ts +9 -11
- package/source/require-exactly-one.d.ts +7 -7
- package/source/require-one-or-none.d.ts +5 -5
- package/source/required-deep.d.ts +3 -1
- package/source/schema.d.ts +16 -8
- package/source/screaming-snake-case.d.ts +1 -0
- package/source/set-non-nullable-deep.d.ts +8 -4
- package/source/set-non-nullable.d.ts +4 -11
- package/source/set-optional.d.ts +6 -10
- package/source/set-parameter-type.d.ts +2 -2
- package/source/set-readonly.d.ts +4 -8
- package/source/set-required-deep.d.ts +3 -2
- package/source/set-required.d.ts +4 -8
- package/source/shared-union-fields-deep.d.ts +5 -4
- package/source/shared-union-fields.d.ts +9 -9
- package/source/snake-case.d.ts +1 -0
- package/source/snake-cased-properties-deep.d.ts +7 -0
- package/source/snake-cased-properties.d.ts +5 -1
- package/source/some-extend.d.ts +115 -0
- package/source/split-on-rest-element.d.ts +6 -4
- package/source/split.d.ts +1 -1
- package/source/spread.d.ts +1 -5
- package/source/string-length.d.ts +38 -0
- package/source/string-repeat.d.ts +48 -21
- package/source/string-slice.d.ts +1 -1
- package/source/string-to-array.d.ts +97 -0
- package/source/string-to-number.d.ts +67 -0
- package/source/subtract.d.ts +4 -3
- package/source/sum.d.ts +5 -4
- package/source/tagged.d.ts +5 -7
- package/source/tsconfig-json.d.ts +40 -8
- package/source/tuple-of.d.ts +42 -8
- package/source/typed-array.d.ts +1 -0
- package/source/union-length.d.ts +27 -0
- package/source/union-member.d.ts +65 -0
- package/source/union-to-intersection.d.ts +1 -1
- package/source/union-to-tuple.d.ts +10 -19
- package/source/unwrap-required.d.ts +37 -0
- package/source/words.d.ts +30 -4
- package/source/writable.d.ts +15 -19
- package/source/xor.d.ts +1 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type {CollapseLiterals, UnwrapBrand} from './internal/object.d.ts';
|
|
2
|
+
import type {IfNotAnyOrNever} from './internal/type.d.ts';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
Returns a boolean for whether the given type is a `number` or `bigint` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
```
|
|
9
|
+
import type {IsNumericLiteral} from 'type-fest';
|
|
10
|
+
|
|
11
|
+
type A = IsNumericLiteral<0>;
|
|
12
|
+
//=> true
|
|
13
|
+
|
|
14
|
+
type B = IsNumericLiteral<number>;
|
|
15
|
+
//=> false
|
|
16
|
+
|
|
17
|
+
type C = IsNumericLiteral<100n>;
|
|
18
|
+
//=> true
|
|
19
|
+
|
|
20
|
+
type D = IsNumericLiteral<bigint>;
|
|
21
|
+
//=> false
|
|
22
|
+
|
|
23
|
+
type E = IsNumericLiteral<1 | 2 | 10n | 20n>;
|
|
24
|
+
//=> true
|
|
25
|
+
|
|
26
|
+
type F = IsNumericLiteral<number | bigint>;
|
|
27
|
+
//=> false
|
|
28
|
+
|
|
29
|
+
type G = IsNumericLiteral<1 | bigint>;
|
|
30
|
+
//=> boolean
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
@category Type Guard
|
|
34
|
+
@category Utilities
|
|
35
|
+
*/
|
|
36
|
+
export type IsNumericLiteral<T> = IfNotAnyOrNever<T, {
|
|
37
|
+
ifNot: _IsNumericLiteral<CollapseLiterals<UnwrapBrand<T>>>;
|
|
38
|
+
ifAny: false;
|
|
39
|
+
ifNever: false;
|
|
40
|
+
}>;
|
|
41
|
+
|
|
42
|
+
type _IsNumericLiteral<T> = T extends number | bigint
|
|
43
|
+
? number extends T
|
|
44
|
+
? false
|
|
45
|
+
: bigint extends T
|
|
46
|
+
? false
|
|
47
|
+
: true
|
|
48
|
+
: false;
|
|
49
|
+
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type {CollapseLiterals, UnwrapBrand} from './internal/object.d.ts';
|
|
2
|
+
import type {IfNotAnyOrNever} from './internal/type.d.ts';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
Returns a boolean for whether the given type is a `string` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
|
|
6
|
+
|
|
7
|
+
The implementation of this type is inspired by the trick mentioned in this [StackOverflow answer](https://stackoverflow.com/a/68261113/420747).
|
|
8
|
+
|
|
9
|
+
@example
|
|
10
|
+
```
|
|
11
|
+
import type {IsStringLiteral} from 'type-fest';
|
|
12
|
+
|
|
13
|
+
type A = IsStringLiteral<'foo'>;
|
|
14
|
+
//=> true
|
|
15
|
+
|
|
16
|
+
type B = IsStringLiteral<string>;
|
|
17
|
+
//=> false
|
|
18
|
+
|
|
19
|
+
// String types with infinite set of possible values return `false`
|
|
20
|
+
type C = IsStringLiteral<`on${string}`>;
|
|
21
|
+
//=> false
|
|
22
|
+
|
|
23
|
+
type D = IsStringLiteral<Uppercase<string>>;
|
|
24
|
+
//=> false
|
|
25
|
+
|
|
26
|
+
type E = IsStringLiteral<'foo' | 'bar' | 'baz'>;
|
|
27
|
+
//=> true
|
|
28
|
+
|
|
29
|
+
type F = IsStringLiteral<'sm' | 'md' | 'lg' | `${number}px`>;
|
|
30
|
+
//=> boolean
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
@example
|
|
34
|
+
```
|
|
35
|
+
import type {IsStringLiteral} from 'type-fest';
|
|
36
|
+
|
|
37
|
+
type StringLength<S extends string, Counter extends never[] = []> =
|
|
38
|
+
IsStringLiteral<S> extends true
|
|
39
|
+
? S extends `${string}${infer Tail}`
|
|
40
|
+
? StringLength<Tail, [...Counter, never]>
|
|
41
|
+
: Counter['length']
|
|
42
|
+
: number; // return `number` for non-literal string types
|
|
43
|
+
|
|
44
|
+
type L1 = StringLength<'foobar'>;
|
|
45
|
+
//=> 6
|
|
46
|
+
|
|
47
|
+
type L2 = StringLength<Lowercase<string>>;
|
|
48
|
+
//=> number
|
|
49
|
+
|
|
50
|
+
type L3 = StringLength<`${number}`>;
|
|
51
|
+
//=> number
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
@category Type Guard
|
|
55
|
+
@category Utilities
|
|
56
|
+
*/
|
|
57
|
+
export type IsStringLiteral<S> = IfNotAnyOrNever<S, {
|
|
58
|
+
ifNot: _IsStringLiteral<CollapseLiterals<UnwrapBrand<S>>>;
|
|
59
|
+
ifAny: false;
|
|
60
|
+
ifNever: false;
|
|
61
|
+
}>;
|
|
62
|
+
|
|
63
|
+
type _IsStringLiteral<S> =
|
|
64
|
+
// If `S` is an infinite string type (e.g., `on${string}`), `Record<S, never>` produces an index signature,
|
|
65
|
+
// and since `{}` extends index signatures, the result becomes `false`.
|
|
66
|
+
S extends string
|
|
67
|
+
? {} extends Record<S, never>
|
|
68
|
+
? false
|
|
69
|
+
: true
|
|
70
|
+
: false;
|
|
71
|
+
|
|
72
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type {CollapseLiterals, UnwrapBrand} from './internal/object.d.ts';
|
|
2
|
+
import type {IfNotAnyOrNever} from './internal/type.d.ts';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
Returns a boolean for whether the given type is a `symbol` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
```
|
|
9
|
+
import type {IsSymbolLiteral} from 'type-fest';
|
|
10
|
+
|
|
11
|
+
declare const symbolLiteral1: unique symbol;
|
|
12
|
+
declare const symbolLiteral2: unique symbol;
|
|
13
|
+
|
|
14
|
+
type A = IsSymbolLiteral<typeof symbolLiteral1>;
|
|
15
|
+
//=> true
|
|
16
|
+
|
|
17
|
+
type B = IsSymbolLiteral<symbol>;
|
|
18
|
+
//=> false
|
|
19
|
+
|
|
20
|
+
type C = IsSymbolLiteral<typeof symbolLiteral1 | typeof symbolLiteral2>;
|
|
21
|
+
//=> true
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
@category Type Guard
|
|
25
|
+
@category Utilities
|
|
26
|
+
*/
|
|
27
|
+
export type IsSymbolLiteral<T> = IfNotAnyOrNever<T, {
|
|
28
|
+
ifNot: _IsSymbolLiteral<CollapseLiterals<UnwrapBrand<T>>>;
|
|
29
|
+
ifAny: false;
|
|
30
|
+
ifNever: false;
|
|
31
|
+
}>;
|
|
32
|
+
|
|
33
|
+
type _IsSymbolLiteral<T> = T extends symbol
|
|
34
|
+
? symbol extends T
|
|
35
|
+
? false
|
|
36
|
+
: true
|
|
37
|
+
: false;
|
|
38
|
+
|
|
39
|
+
export {};
|
package/source/is-union.d.ts
CHANGED
|
@@ -21,20 +21,20 @@ export type IsUnion<T> = InternalIsUnion<T>;
|
|
|
21
21
|
The actual implementation of `IsUnion`.
|
|
22
22
|
*/
|
|
23
23
|
type InternalIsUnion<T, U = T> =
|
|
24
|
-
(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
) extends infer Result
|
|
24
|
+
(
|
|
25
|
+
IsNever<T> extends true
|
|
26
|
+
? false
|
|
27
|
+
: T extends any
|
|
28
|
+
? IsEqual<U, T> extends true
|
|
29
|
+
? false
|
|
30
|
+
: true
|
|
31
|
+
: never
|
|
32
|
+
) extends infer Result
|
|
33
33
|
// In some cases `Result` will return `false | true` which is `boolean`,
|
|
34
34
|
// that means `T` has at least two types and it's a union type,
|
|
35
35
|
// so we will return `true` instead of `boolean`.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
? boolean extends Result ? true
|
|
37
|
+
: Result
|
|
38
|
+
: never; // Should never happen
|
|
39
39
|
|
|
40
40
|
export {};
|
|
@@ -57,10 +57,10 @@ type Fruit = IterableElement<typeof fruits>;
|
|
|
57
57
|
@category Iterable
|
|
58
58
|
*/
|
|
59
59
|
export type IterableElement<TargetIterable> =
|
|
60
|
-
TargetIterable extends Iterable<infer ElementType>
|
|
61
|
-
ElementType
|
|
62
|
-
TargetIterable extends AsyncIterable<infer ElementType>
|
|
63
|
-
ElementType
|
|
64
|
-
never;
|
|
60
|
+
TargetIterable extends Iterable<infer ElementType>
|
|
61
|
+
? ElementType
|
|
62
|
+
: TargetIterable extends AsyncIterable<infer ElementType>
|
|
63
|
+
? ElementType
|
|
64
|
+
: never;
|
|
65
65
|
|
|
66
66
|
export {};
|
package/source/jsonify.d.ts
CHANGED
|
@@ -25,15 +25,11 @@ type JsonifyList<T extends UnknownArray> = T extends readonly []
|
|
|
25
25
|
? JsonValue[]
|
|
26
26
|
: Array<T[number] extends NotJsonable ? null : Jsonify<UndefinedToNull<T[number]>>>;
|
|
27
27
|
|
|
28
|
-
type FilterJsonableKeys<T extends object> = {
|
|
29
|
-
[Key in keyof T]: T[Key] extends NotJsonable ? never : Key;
|
|
30
|
-
}[keyof T];
|
|
31
|
-
|
|
32
28
|
/**
|
|
33
29
|
JSON serialize objects (not including arrays) and classes.
|
|
34
30
|
*/
|
|
35
31
|
type JsonifyObject<T extends object> = {
|
|
36
|
-
[Key in keyof
|
|
32
|
+
[Key in keyof T as T[Key] extends NotJsonable ? never : Key]: Jsonify<T[Key]>;
|
|
37
33
|
};
|
|
38
34
|
|
|
39
35
|
/**
|
|
@@ -98,13 +94,13 @@ export type Jsonify<T> = IsAny<T> extends true
|
|
|
98
94
|
? null
|
|
99
95
|
: T extends JsonPrimitive
|
|
100
96
|
? T
|
|
101
|
-
|
|
102
|
-
T extends {toJSON(): infer J}
|
|
97
|
+
// Any object with toJSON is special case
|
|
98
|
+
: T extends {toJSON(): infer J}
|
|
103
99
|
? (() => J) extends () => JsonValue // Is J assignable to JsonValue?
|
|
104
100
|
? J // Then T is Jsonable and its Jsonable value is J
|
|
105
101
|
: Jsonify<J> // Maybe if we look a level deeper we'll find a JsonValue
|
|
106
|
-
|
|
107
|
-
T extends Number
|
|
102
|
+
// Instanced primitives are objects
|
|
103
|
+
: T extends Number
|
|
108
104
|
? number
|
|
109
105
|
: T extends String
|
|
110
106
|
? string
|
package/source/kebab-case.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type {KebabCase} from 'type-fest';
|
|
|
15
15
|
|
|
16
16
|
const someVariable: KebabCase<'fooBar'> = 'foo-bar';
|
|
17
17
|
const someVariableNoSplitOnNumbers: KebabCase<'p2pNetwork', {splitOnNumbers: false}> = 'p2p-network';
|
|
18
|
+
const someVariableWithPunctuation: KebabCase<'div.card::after', {splitOnPunctuation: true}> = 'div-card-after';
|
|
18
19
|
|
|
19
20
|
// Advanced
|
|
20
21
|
|
|
@@ -51,6 +51,13 @@ const splitOnNumbers: KebabCasedPropertiesDeep<{line1: {line2: [{line3: string}]
|
|
|
51
51
|
],
|
|
52
52
|
},
|
|
53
53
|
};
|
|
54
|
+
|
|
55
|
+
const splitOnPunctuation: KebabCasedPropertiesDeep<{'user@info': {'user::id': number; 'user::name': string}}, {splitOnPunctuation: true}> = {
|
|
56
|
+
'user-info': {
|
|
57
|
+
'user-id': 1,
|
|
58
|
+
'user-name': 'Tom',
|
|
59
|
+
},
|
|
60
|
+
};
|
|
54
61
|
```
|
|
55
62
|
|
|
56
63
|
@category Change case
|
|
@@ -4,7 +4,7 @@ import type {ApplyDefaultOptions} from './internal/index.d.ts';
|
|
|
4
4
|
import type {WordsOptions} from './words.d.ts';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
Convert object properties to kebab case
|
|
7
|
+
Convert top-level object properties to kebab case.
|
|
8
8
|
|
|
9
9
|
This can be useful when, for example, converting some API types from a different style.
|
|
10
10
|
|
|
@@ -28,6 +28,10 @@ const result: KebabCasedProperties<User> = {
|
|
|
28
28
|
const splitOnNumbers: KebabCasedProperties<{line1: string}, {splitOnNumbers: true}> = {
|
|
29
29
|
'line-1': 'string',
|
|
30
30
|
};
|
|
31
|
+
|
|
32
|
+
const splitOnPunctuation: KebabCasedProperties<{'foo::bar': string}, {splitOnPunctuation: true}> = {
|
|
33
|
+
'foo-bar': 'string',
|
|
34
|
+
};
|
|
31
35
|
```
|
|
32
36
|
|
|
33
37
|
@category Change case
|
|
@@ -38,7 +38,7 @@ type AllKeys = KeysOfUnion<Union>;
|
|
|
38
38
|
@category Object
|
|
39
39
|
*/
|
|
40
40
|
export type KeysOfUnion<ObjectType> =
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
// Hack to fix https://github.com/sindresorhus/type-fest/issues/1008
|
|
42
|
+
keyof UnionToIntersection<ObjectType extends unknown ? Record<keyof ObjectType, never> : never>;
|
|
43
43
|
|
|
44
44
|
export {};
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import type {If} from './if.d.ts';
|
|
2
|
+
import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled} from './internal/type.d.ts';
|
|
3
|
+
import type {SplitOnRestElement} from './split-on-rest-element.d.ts';
|
|
4
|
+
import type {UnknownArray} from './unknown-array.d.ts';
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
Extract the type of the last element of an array.
|
|
3
8
|
|
|
@@ -16,21 +21,69 @@ const last2 = lastOf([true, false, 'baz', 10]);
|
|
|
16
21
|
//=> 10
|
|
17
22
|
```
|
|
18
23
|
|
|
24
|
+
Note: When the array ends with an optional or rest element, the last element's position becomes ambiguous. In such cases, the result is a union of the types of all elements that could potentially be the last element of the array.
|
|
25
|
+
|
|
26
|
+
@example
|
|
27
|
+
```
|
|
28
|
+
import type {LastArrayElement} from 'type-fest';
|
|
29
|
+
|
|
30
|
+
type A = LastArrayElement<[string, number?, bigint?]>;
|
|
31
|
+
//=> bigint | number | string
|
|
32
|
+
|
|
33
|
+
type B = LastArrayElement<[string, number, bigint?, ...boolean[]]>;
|
|
34
|
+
//=> boolean | bigint | number
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Note: If empty array is a valid value for the array type, the result includes an `undefined`. This aligns with the runtime behavior of `[].at(-1)`.
|
|
38
|
+
|
|
39
|
+
@example
|
|
40
|
+
```
|
|
41
|
+
import type {LastArrayElement} from 'type-fest';
|
|
42
|
+
|
|
43
|
+
type A = LastArrayElement<[]>;
|
|
44
|
+
//=> undefined
|
|
45
|
+
|
|
46
|
+
// `[]` is assignable to `string[]`
|
|
47
|
+
type B = LastArrayElement<string[]>;
|
|
48
|
+
//=> string | undefined
|
|
49
|
+
|
|
50
|
+
// `[]` is assignable to `[string?, number?]`
|
|
51
|
+
type C = LastArrayElement<[string?, number?]>;
|
|
52
|
+
//=> number | string | undefined
|
|
53
|
+
|
|
54
|
+
// `[]` is assignable to [string?, number?, ...bigint[]]`
|
|
55
|
+
type D = LastArrayElement<[string?, number?, ...bigint[]]>;
|
|
56
|
+
//=> bigint | number | string | undefined
|
|
57
|
+
```
|
|
58
|
+
|
|
19
59
|
@category Array
|
|
20
60
|
@category Template literal
|
|
21
61
|
*/
|
|
22
|
-
export type LastArrayElement<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
62
|
+
export type LastArrayElement<TArray extends UnknownArray> =
|
|
63
|
+
IfNotAnyOrNever<TArray, {
|
|
64
|
+
ifNot: TArray extends UnknownArray // For distributing `TArray`
|
|
65
|
+
? SplitOnRestElement<TArray> extends readonly [infer BeforeRest extends UnknownArray, infer Rest extends UnknownArray, infer AfterRest extends UnknownArray]
|
|
66
|
+
? _LastArrayElement<BeforeRest, Rest, AfterRest>
|
|
67
|
+
: never
|
|
68
|
+
: never;
|
|
69
|
+
}>;
|
|
70
|
+
|
|
71
|
+
type _LastArrayElement<BeforeRest extends UnknownArray, Rest extends UnknownArray, AfterRest extends UnknownArray> =
|
|
72
|
+
AfterRest extends readonly [...any, infer Last] // Note there are no optional elements in `AfterRest`.
|
|
73
|
+
? Last // If there's a `Last` in `AfterRest`, then that's the result.
|
|
74
|
+
: Rest[number] | BeforeRestLastElement<BeforeRest>; // Otherwise, the result is union of the `Rest` element and the last element in `BeforeRest`.
|
|
75
|
+
|
|
76
|
+
type BeforeRestLastElement<BeforeRest extends UnknownArray, Accumulator = never> =
|
|
77
|
+
BeforeRest extends readonly []
|
|
78
|
+
? Accumulator | undefined
|
|
79
|
+
: BeforeRest extends readonly [...any, infer Last]
|
|
80
|
+
? Last | Accumulator
|
|
81
|
+
: BeforeRest extends readonly [...infer Rest, (infer Last)?]
|
|
82
|
+
? BeforeRestLastElement<
|
|
83
|
+
Rest,
|
|
84
|
+
// Add `undefined` for optional elements, if `exactOptionalPropertyTypes` is disabled.
|
|
85
|
+
Last | Accumulator | If<IsExactOptionalPropertyTypesEnabled, never, undefined>
|
|
86
|
+
>
|
|
87
|
+
: never;
|
|
35
88
|
|
|
36
89
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {GreaterThan} from './greater-than.d.ts';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
|
|
4
|
+
Returns a boolean for whether a given number is less than or equal to another number.
|
|
5
5
|
|
|
6
6
|
@example
|
|
7
7
|
```
|
|
@@ -16,9 +16,45 @@ type B = LessThanOrEqual<1, 1>;
|
|
|
16
16
|
type C = LessThanOrEqual<1, 5>;
|
|
17
17
|
//=> true
|
|
18
18
|
```
|
|
19
|
+
|
|
20
|
+
Note: If either argument is the non-literal `number` type, the result is `boolean`.
|
|
21
|
+
|
|
22
|
+
@example
|
|
23
|
+
```
|
|
24
|
+
import type {LessThanOrEqual} from 'type-fest';
|
|
25
|
+
|
|
26
|
+
type A = LessThanOrEqual<number, 1>;
|
|
27
|
+
//=> boolean
|
|
28
|
+
|
|
29
|
+
type B = LessThanOrEqual<1, number>;
|
|
30
|
+
//=> boolean
|
|
31
|
+
|
|
32
|
+
type C = LessThanOrEqual<number, number>;
|
|
33
|
+
//=> boolean
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
@example
|
|
37
|
+
```
|
|
38
|
+
import type {LessThanOrEqual} from 'type-fest';
|
|
39
|
+
|
|
40
|
+
// Use `LessThanOrEqual` to constrain a function parameter to non-positive numbers.
|
|
41
|
+
declare function setNonPositive<N extends number>(value: LessThanOrEqual<N, 0> extends true ? N : never): void;
|
|
42
|
+
|
|
43
|
+
setNonPositive(0); // ✅ Allowed
|
|
44
|
+
setNonPositive(-1); // ✅ Allowed
|
|
45
|
+
|
|
46
|
+
// @ts-expect-error
|
|
47
|
+
setNonPositive(1);
|
|
48
|
+
|
|
49
|
+
// @ts-expect-error
|
|
50
|
+
setNonPositive(2);
|
|
51
|
+
```
|
|
19
52
|
*/
|
|
20
|
-
export type LessThanOrEqual<A extends number, B extends number> =
|
|
21
|
-
|
|
22
|
-
|
|
53
|
+
export type LessThanOrEqual<A extends number, B extends number> =
|
|
54
|
+
GreaterThan<A, B> extends infer Result
|
|
55
|
+
? Result extends true
|
|
56
|
+
? false
|
|
57
|
+
: true
|
|
58
|
+
: never; // Should never happen
|
|
23
59
|
|
|
24
60
|
export {};
|
package/source/less-than.d.ts
CHANGED
|
@@ -16,10 +16,42 @@ type B = LessThan<1, 1>;
|
|
|
16
16
|
type C = LessThan<1, 5>;
|
|
17
17
|
//=> true
|
|
18
18
|
```
|
|
19
|
+
|
|
20
|
+
Note: If either argument is the non-literal `number` type, the result is `boolean`.
|
|
21
|
+
|
|
22
|
+
@example
|
|
23
|
+
```
|
|
24
|
+
import type {LessThan} from 'type-fest';
|
|
25
|
+
|
|
26
|
+
type A = LessThan<number, 1>;
|
|
27
|
+
//=> boolean
|
|
28
|
+
|
|
29
|
+
type B = LessThan<1, number>;
|
|
30
|
+
//=> boolean
|
|
31
|
+
|
|
32
|
+
type C = LessThan<number, number>;
|
|
33
|
+
//=> boolean
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
@example
|
|
37
|
+
```
|
|
38
|
+
import type {LessThan} from 'type-fest';
|
|
39
|
+
|
|
40
|
+
// Use `LessThan` to constrain a function parameter to negative numbers.
|
|
41
|
+
declare function setNegative<N extends number>(value: LessThan<N, 0> extends true ? N : never): void;
|
|
42
|
+
|
|
43
|
+
setNegative(-1); // ✅ Allowed
|
|
44
|
+
setNegative(-2); // ✅ Allowed
|
|
45
|
+
|
|
46
|
+
// @ts-expect-error
|
|
47
|
+
setNegative(0);
|
|
48
|
+
|
|
49
|
+
// @ts-expect-error
|
|
50
|
+
setNegative(1);
|
|
51
|
+
```
|
|
19
52
|
*/
|
|
20
|
-
export type LessThan<A extends number, B extends number> =
|
|
21
|
-
|
|
22
|
-
: GreaterThanOrEqual<A, B> extends infer Result
|
|
53
|
+
export type LessThan<A extends number, B extends number> =
|
|
54
|
+
GreaterThanOrEqual<A, B> extends infer Result
|
|
23
55
|
? Result extends true
|
|
24
56
|
? false
|
|
25
57
|
: true
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
Given a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) return the
|
|
2
|
+
Given a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) return the [primitive type](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) it belongs to, or `never` if it's not a primitive.
|
|
3
3
|
|
|
4
4
|
Use-case: Working with generic types that may be literal types.
|
|
5
5
|
|
|
@@ -3,7 +3,7 @@ import type {Primitive} from './primitive.d.ts';
|
|
|
3
3
|
export type _LiteralStringUnion<T> = LiteralUnion<T, string>;
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
|
|
6
|
+
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.
|
|
7
7
|
|
|
8
8
|
Currently, when a union type of a primitive type is combined with literal types, TypeScript loses all information about the combined literals. Thus, when such type is used in an IDE with autocompletion, no suggestions are made for the declared literals.
|
|
9
9
|
|
|
@@ -38,8 +38,8 @@ exclusiveOptions = {exclusive1: true, exclusive2: 'hi'};
|
|
|
38
38
|
@category Object
|
|
39
39
|
*/
|
|
40
40
|
export type MergeExclusive<FirstType, SecondType> =
|
|
41
|
-
(FirstType | SecondType) extends object
|
|
42
|
-
(Without<FirstType, SecondType> & SecondType) | (Without<SecondType, FirstType> & FirstType)
|
|
43
|
-
FirstType | SecondType;
|
|
41
|
+
(FirstType | SecondType) extends object
|
|
42
|
+
? (Without<FirstType, SecondType> & SecondType) | (Without<SecondType, FirstType> & FirstType)
|
|
43
|
+
: FirstType | SecondType;
|
|
44
44
|
|
|
45
45
|
export {};
|
package/source/merge.d.ts
CHANGED
|
@@ -12,6 +12,31 @@ type SimpleMerge<Destination, Source> = Simplify<{
|
|
|
12
12
|
/**
|
|
13
13
|
Merge two types into a new type. Keys of the second type overrides keys of the first type.
|
|
14
14
|
|
|
15
|
+
This is different from the TypeScript `&` (intersection) operator. With `&`, conflicting property types are intersected, which often results in `never`. For example, `{a: string} & {a: number}` makes `a` become `string & number`, which resolves to `never`. With `Merge`, the second type's keys cleanly override the first, so `Merge<{a: string}, {a: number}>` gives `{a: number}` as expected. `Merge` also produces a flattened type (via `Simplify`), making it more readable in IDE tooltips compared to `A & B`.
|
|
16
|
+
|
|
17
|
+
@example
|
|
18
|
+
```
|
|
19
|
+
import type {Merge} from 'type-fest';
|
|
20
|
+
|
|
21
|
+
type Foo = {
|
|
22
|
+
a: string;
|
|
23
|
+
b: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type Bar = {
|
|
27
|
+
a: number; // Conflicts with Foo['a']
|
|
28
|
+
c: boolean;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// With `&`, `a` becomes `string & number` which is `never`. Not what you want.
|
|
32
|
+
type WithIntersection = (Foo & Bar)['a'];
|
|
33
|
+
//=> never
|
|
34
|
+
|
|
35
|
+
// With `Merge`, `a` is cleanly overridden to `number`.
|
|
36
|
+
type WithMerge = Merge<Foo, Bar>['a'];
|
|
37
|
+
//=> number
|
|
38
|
+
```
|
|
39
|
+
|
|
15
40
|
@example
|
|
16
41
|
```
|
|
17
42
|
import type {Merge} from 'type-fest';
|
|
@@ -4,7 +4,7 @@ import type {IsEqual} from './is-equal.d.ts';
|
|
|
4
4
|
type Recursive<T> = Array<Recursive<T>>;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
|
|
7
|
+
Create a type that represents a multidimensional array of the given type and dimension.
|
|
8
8
|
|
|
9
9
|
Use-cases:
|
|
10
10
|
- Return a n-dimensional array from functions.
|
|
@@ -4,7 +4,7 @@ import type {IsEqual} from './is-equal.d.ts';
|
|
|
4
4
|
type Recursive<T> = ReadonlyArray<Recursive<T>>;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
|
|
7
|
+
Create a type that represents a multidimensional readonly array of the given type and dimension.
|
|
8
8
|
|
|
9
9
|
Use-cases:
|
|
10
10
|
- Return a n-dimensional array from functions.
|