type-fest 4.12.0 → 4.13.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 +1 -0
- package/package.json +1 -1
- package/readme.md +2 -0
- package/source/array-slice.d.ts +29 -16
- package/source/distributed-omit.d.ts +89 -0
- package/source/omit-deep.d.ts +9 -5
- package/source/set-parameter-type.d.ts +60 -14
- package/source/subtract.d.ts +31 -29
- package/source/sum.d.ts +30 -28
package/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * from './source/observable-like';
|
|
|
6
6
|
|
|
7
7
|
// Utilities
|
|
8
8
|
export type {KeysOfUnion} from './source/keys-of-union';
|
|
9
|
+
export type {DistributedOmit} from './source/distributed-omit';
|
|
9
10
|
export type {EmptyObject, IsEmptyObject} from './source/empty-object';
|
|
10
11
|
export type {NonEmptyObject} from './source/non-empty-object';
|
|
11
12
|
export type {UnknownRecord} from './source/unknown-record';
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -182,6 +182,7 @@ Click the type names for complete docs.
|
|
|
182
182
|
- [`SetFieldType`](source/set-field-type.d.ts) - Create a type that changes the type of the given keys.
|
|
183
183
|
- [`Paths`](source/paths.d.ts) - Generate a union of all possible paths to properties in the given object.
|
|
184
184
|
- [`SharedUnionFieldsDeep`](source/shared-union-fields-deep.d.ts) - Create a type with shared fields from a union of object types, deeply traversing nested structures.
|
|
185
|
+
- [`DistributedOmit`](source/distributed-omit.d.ts) - Omits keys from a type, distributing the operation over a union.
|
|
185
186
|
|
|
186
187
|
### Type Guard
|
|
187
188
|
|
|
@@ -323,6 +324,7 @@ type ShouldBeNever = IfAny<'not any', 'not never', 'never'>;
|
|
|
323
324
|
- `RequireOnlyOne` - See [`RequireExactlyOne`](source/require-exactly-one.d.ts)
|
|
324
325
|
- `AtMostOne` - See [`RequireOneOrNone`](source/require-one-or-none.d.ts)
|
|
325
326
|
- `AllKeys` - See [`KeysOfUnion`](source/keys-of-union.d.ts)
|
|
327
|
+
- `Branded` - See [`Opaque`](source/opaque.d.ts)
|
|
326
328
|
|
|
327
329
|
## Tips
|
|
328
330
|
|
package/source/array-slice.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type {Sum} from './sum';
|
|
2
|
-
import type {LessThan} from './less-than';
|
|
3
2
|
import type {LessThanOrEqual} from './less-than-or-equal';
|
|
3
|
+
import type {GreaterThanOrEqual} from './greater-than-or-equal';
|
|
4
|
+
import type {GreaterThan} from './greater-than';
|
|
4
5
|
import type {IsNegative} from './numeric';
|
|
5
|
-
import type {And} from './internal';
|
|
6
|
+
import type {And, Not, ArrayMin} from './internal';
|
|
6
7
|
import type {IsEqual} from './is-equal';
|
|
8
|
+
import type {ArraySplice} from './array-splice';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
Returns an array slice of a given range, just like `Array#slice()`.
|
|
@@ -54,9 +56,26 @@ slice[3];
|
|
|
54
56
|
*/
|
|
55
57
|
export type ArraySlice<
|
|
56
58
|
Array_ extends readonly unknown[],
|
|
57
|
-
Start extends number =
|
|
58
|
-
End extends number =
|
|
59
|
-
> =
|
|
59
|
+
Start extends number = never,
|
|
60
|
+
End extends number = never,
|
|
61
|
+
> = And<IsEqual<Start, never>, IsEqual<End, never>> extends true
|
|
62
|
+
? Array_
|
|
63
|
+
: number extends Array_['length']
|
|
64
|
+
? VariableLengthArraySliceHelper<Array_, Start, End>
|
|
65
|
+
: ArraySliceHelper<Array_, IsEqual<Start, never> extends true ? 0 : Start, IsEqual<End, never> extends true ? Array_['length'] : End>;
|
|
66
|
+
|
|
67
|
+
type VariableLengthArraySliceHelper<
|
|
68
|
+
Array_ extends readonly unknown[],
|
|
69
|
+
Start extends number,
|
|
70
|
+
End extends number,
|
|
71
|
+
> = And<Not<IsNegative<Start>>, IsEqual<End, never>> extends true
|
|
72
|
+
? ArraySplice<Array_, 0, Start>
|
|
73
|
+
: And<
|
|
74
|
+
And<Not<IsNegative<Start>>, Not<IsNegative<End>>>,
|
|
75
|
+
IsEqual<GreaterThan<End, Start>, true>
|
|
76
|
+
> extends true
|
|
77
|
+
? ArraySliceByPositiveIndex<Array_, Start, End>
|
|
78
|
+
: [];
|
|
60
79
|
|
|
61
80
|
type ArraySliceHelper<
|
|
62
81
|
Array_ extends readonly unknown[],
|
|
@@ -73,21 +92,15 @@ type ArraySliceHelper<
|
|
|
73
92
|
: never
|
|
74
93
|
: Start,
|
|
75
94
|
PositiveE extends number = IsNegative<End> extends true ? Sum<ArrayLength, End> : End,
|
|
76
|
-
> = true extends [IsNegative<PositiveS>, LessThanOrEqual<PositiveE, PositiveS>][number]
|
|
95
|
+
> = true extends [IsNegative<PositiveS>, LessThanOrEqual<PositiveE, PositiveS>, GreaterThanOrEqual<PositiveS, ArrayLength>][number]
|
|
77
96
|
? []
|
|
78
|
-
: ArraySliceByPositiveIndex<Array_, PositiveS, PositiveE
|
|
97
|
+
: ArraySliceByPositiveIndex<Array_, ArrayMin<[PositiveS, ArrayLength]>, ArrayMin<[PositiveE, ArrayLength]>>;
|
|
79
98
|
|
|
80
99
|
type ArraySliceByPositiveIndex<
|
|
81
100
|
Array_ extends readonly unknown[],
|
|
82
101
|
Start extends number,
|
|
83
102
|
End extends number,
|
|
84
|
-
TraversedElement extends Array<Array_[number]> = [],
|
|
85
103
|
Result extends Array<Array_[number]> = [],
|
|
86
|
-
> =
|
|
87
|
-
?
|
|
88
|
-
|
|
89
|
-
IsEqual<LessThan<TraversedElement['length'], End>, true>
|
|
90
|
-
> extends true
|
|
91
|
-
? ArraySliceByPositiveIndex<Rest, Start, End, [...TraversedElement, H], [...Result, H]>
|
|
92
|
-
: ArraySliceByPositiveIndex<Rest, Start, End, [...TraversedElement, H], Result>
|
|
93
|
-
: Result;
|
|
104
|
+
> = Start extends End
|
|
105
|
+
? Result
|
|
106
|
+
: ArraySliceByPositiveIndex<Array_, Sum<Start, 1>, End, [...Result, Array_[Start]]>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type {KeysOfUnion} from './keys-of-union';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Omits keys from a type, distributing the operation over a union.
|
|
5
|
+
|
|
6
|
+
TypeScript's `Omit` doesn't distribute over unions, leading to the erasure of unique properties from union members when omitting keys. This creates a type that only retains properties common to all union members, making it impossible to access member-specific properties after the Omit. Essentially, using `Omit` on a union type merges the types into a less specific one, hindering type narrowing and property access based on discriminants. This type solves that.
|
|
7
|
+
|
|
8
|
+
Example:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
type A = {
|
|
12
|
+
discriminant: 'A';
|
|
13
|
+
foo: string;
|
|
14
|
+
a: number;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type B = {
|
|
18
|
+
discriminant: 'B';
|
|
19
|
+
foo: string;
|
|
20
|
+
b: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type Union = A | B;
|
|
24
|
+
|
|
25
|
+
type OmittedUnion = Omit<Union, 'foo'>;
|
|
26
|
+
//=> {discriminant: 'A' | 'B'}
|
|
27
|
+
|
|
28
|
+
const omittedUnion: OmittedUnion = createOmittedUnion();
|
|
29
|
+
|
|
30
|
+
if (omittedUnion.discriminant === 'A') {
|
|
31
|
+
// We would like to narrow `omittedUnion`'s type
|
|
32
|
+
// to `A` here, but we can't because `Omit`
|
|
33
|
+
// doesn't distribute over unions.
|
|
34
|
+
|
|
35
|
+
omittedUnion.a;
|
|
36
|
+
//=> Error: `a` is not a property of `{discriminant: 'A' | 'B'}`
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
While `Except` solves this problem, it restricts the keys you can omit to the ones that are present in **ALL** union members, where `DistributedOmit` allows you to omit keys that are present in **ANY** union member.
|
|
41
|
+
|
|
42
|
+
@example
|
|
43
|
+
```
|
|
44
|
+
type A = {
|
|
45
|
+
discriminant: 'A';
|
|
46
|
+
foo: string;
|
|
47
|
+
a: number;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
type B = {
|
|
51
|
+
discriminant: 'B';
|
|
52
|
+
foo: string;
|
|
53
|
+
bar: string;
|
|
54
|
+
b: string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
type C = {
|
|
58
|
+
discriminant: 'C';
|
|
59
|
+
bar: string;
|
|
60
|
+
c: boolean;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Notice that `foo` exists in `A` and `B`, but not in `C`, and
|
|
64
|
+
// `bar` exists in `B` and `C`, but not in `A`.
|
|
65
|
+
|
|
66
|
+
type Union = A | B | C;
|
|
67
|
+
|
|
68
|
+
type OmittedUnion = DistributedOmit<Union, 'foo' | 'bar'>;
|
|
69
|
+
|
|
70
|
+
const omittedUnion: OmittedUnion = createOmittedUnion();
|
|
71
|
+
|
|
72
|
+
if (omittedUnion.discriminant === 'A') {
|
|
73
|
+
omittedUnion.a;
|
|
74
|
+
//=> OK
|
|
75
|
+
|
|
76
|
+
omittedUnion.foo;
|
|
77
|
+
//=> Error: `foo` is not a property of `{discriminant: 'A'; a: string}`
|
|
78
|
+
|
|
79
|
+
omittedUnion.bar;
|
|
80
|
+
//=> Error: `bar` is not a property of `{discriminant: 'A'; a: string}`
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
@category Object
|
|
85
|
+
*/
|
|
86
|
+
export type DistributedOmit<ObjectType, KeyType extends KeysOfUnion<ObjectType>> =
|
|
87
|
+
ObjectType extends unknown
|
|
88
|
+
? Omit<ObjectType, KeyType>
|
|
89
|
+
: never;
|
package/source/omit-deep.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type {ArraySplice} from './array-splice';
|
|
2
2
|
import type {ExactKey, IsArrayReadonly, NonRecursiveType, SetArrayAccess, ToString} from './internal';
|
|
3
3
|
import type {IsEqual} from './is-equal';
|
|
4
|
+
import type {IsNever} from './is-never';
|
|
5
|
+
import type {LiteralUnion} from './literal-union';
|
|
4
6
|
import type {SimplifyDeep} from './merge-deep';
|
|
5
7
|
import type {Paths} from './paths';
|
|
6
8
|
import type {SharedUnionFieldsDeep} from './shared-union-fields-deep';
|
|
@@ -69,7 +71,7 @@ type AddressInfo = OmitDeep<Info1, 'address.1.foo'>;
|
|
|
69
71
|
@category Object
|
|
70
72
|
@category Array
|
|
71
73
|
*/
|
|
72
|
-
export type OmitDeep<T, PathUnion extends Paths<T>> =
|
|
74
|
+
export type OmitDeep<T, PathUnion extends LiteralUnion<Paths<T>, string>> =
|
|
73
75
|
SimplifyDeep<
|
|
74
76
|
SharedUnionFieldsDeep<
|
|
75
77
|
{[P in PathUnion]: OmitDeepWithOnePath<T, P>}[PathUnion]
|
|
@@ -102,9 +104,11 @@ P extends `${infer RecordKeyInPath}.${infer SubPath}`
|
|
|
102
104
|
: ObjectT[Key]
|
|
103
105
|
}
|
|
104
106
|
: ExactKey<ObjectT, P> extends infer Key
|
|
105
|
-
? Key extends
|
|
106
|
-
?
|
|
107
|
-
:
|
|
107
|
+
? IsNever<Key> extends true
|
|
108
|
+
? ObjectT
|
|
109
|
+
: Key extends PropertyKey
|
|
110
|
+
? Omit<ObjectT, Key>
|
|
111
|
+
: ObjectT
|
|
108
112
|
: ObjectT;
|
|
109
113
|
|
|
110
114
|
/**
|
|
@@ -133,4 +137,4 @@ type OmitDeepArrayWithOnePath<ArrayType extends UnknownArray, P extends string |
|
|
|
133
137
|
? []
|
|
134
138
|
// If `ArrayIndex` is a number literal
|
|
135
139
|
: ArraySplice<ArrayType, ArrayIndex, 1, [unknown]>
|
|
136
|
-
:
|
|
140
|
+
: ArrayType;
|
|
@@ -1,17 +1,53 @@
|
|
|
1
1
|
import type {IsUnknown} from './is-unknown';
|
|
2
|
+
import type {StaticPartOfArray} from './internal';
|
|
3
|
+
import type {UnknownArray} from './unknown-array';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
|
-
Create
|
|
6
|
+
Create an array that replaces the given `TArray`'s elements with the given `TObject`'s values at the given indices.
|
|
7
|
+
|
|
8
|
+
`TArray` and `TObject` supports tailing spread array like `[string, ...boolean[]]`, but does not support `[string, ...boolean[], number]`.
|
|
9
|
+
|
|
10
|
+
@example:
|
|
11
|
+
```ts
|
|
12
|
+
// object
|
|
13
|
+
type A = MergeObjectToArray<[string, number], {0: boolean}>;
|
|
14
|
+
//=> [boolean, number]
|
|
15
|
+
|
|
16
|
+
// array
|
|
17
|
+
type B = MergeObjectToArray<[string, number], [boolean]>;
|
|
18
|
+
//=> [boolean, number]
|
|
19
|
+
|
|
20
|
+
// tailing spread array
|
|
21
|
+
type C = MergeObjectToArray<[string, ...boolean[]], {1: number}>;
|
|
22
|
+
//=> [string, ...number[]]
|
|
23
|
+
|
|
24
|
+
type D = MergeObjectToArray<[string, ...boolean[]], [number, ...string[]]>;
|
|
25
|
+
//=> [number, ...string[]]
|
|
26
|
+
```
|
|
5
27
|
*/
|
|
6
|
-
type
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
28
|
+
type MergeObjectToArray<TArray extends UnknownArray, TObject, TArrayCopy extends UnknownArray = TArray> =
|
|
29
|
+
// If `TObject` is an array like `[0, 1, 2]`
|
|
30
|
+
TObject extends UnknownArray
|
|
31
|
+
// If `TObject` is a variable length array, we should use `TObject`'s type as the result type.
|
|
32
|
+
? number extends TObject['length']
|
|
33
|
+
? TObject
|
|
34
|
+
: {
|
|
35
|
+
[K in keyof TArray]: K extends keyof TObject ? TObject[K] : TArray[K]
|
|
36
|
+
}
|
|
37
|
+
: TObject extends object
|
|
38
|
+
// If `TObject` is a object witch key is number like `{0: string, 1: number}`
|
|
39
|
+
? {
|
|
40
|
+
[K in keyof TArray]:
|
|
41
|
+
K extends `${infer NumberK extends number}`
|
|
42
|
+
? NumberK extends keyof TObject ? TObject[NumberK] : TArray[K]
|
|
43
|
+
: number extends K
|
|
44
|
+
// If array key `K` is `number`, means it's a rest parameter, we should set the rest parameter type to corresponding type in `TObject`.
|
|
45
|
+
// example: `MergeObjectToParamterArray<[string, ...boolean[]], {1: number}>` => `[string, ...number[]]`
|
|
46
|
+
? StaticPartOfArray<TArrayCopy>['length'] extends keyof TObject
|
|
47
|
+
? TObject[StaticPartOfArray<TArrayCopy>['length']]
|
|
48
|
+
: TArray[K]
|
|
49
|
+
: never
|
|
50
|
+
} : never;
|
|
15
51
|
|
|
16
52
|
/**
|
|
17
53
|
Create a function that replaces some parameters with the given parameters.
|
|
@@ -39,7 +75,7 @@ Use-case:
|
|
|
39
75
|
```
|
|
40
76
|
import type {SetParameterType} from 'type-fest';
|
|
41
77
|
|
|
42
|
-
type HandleMessage = (data: Data, message: string) => void;
|
|
78
|
+
type HandleMessage = (data: Data, message: string, ...arguments: any[]) => void;
|
|
43
79
|
|
|
44
80
|
type HandleOk = SetParameterType<HandleMessage, {0: SuccessData, 1: 'ok'}>;
|
|
45
81
|
//=> type HandleOk = (data: SuccessData, message: 'ok') => void;
|
|
@@ -48,9 +84,19 @@ type HandleOk = SetParameterType<HandleMessage, {0: SuccessData, 1: 'ok'}>;
|
|
|
48
84
|
type HandleError = SetParameterType<HandleMessage, [data: ErrorData, message: 'error']>;
|
|
49
85
|
//=> type HandleError = (data: ErrorData, message: 'error') => void;
|
|
50
86
|
|
|
51
|
-
//
|
|
87
|
+
// Change single parameter type.
|
|
52
88
|
type HandleWarn = SetParameterType<HandleMessage, {1: 'warn'}>;
|
|
53
89
|
//=> type HandleWarn = (data: Data, message: 'warn') => void;
|
|
90
|
+
|
|
91
|
+
// Change rest parameter type.
|
|
92
|
+
|
|
93
|
+
// Way 1: Input full parameter type.
|
|
94
|
+
type HandleLog = SetParameterType<HandleMessage, [data: Data, message: 'log', ...arguments: string[]]>;
|
|
95
|
+
//=> type HandleLog = (data: Data, message: 'log', ...arguments: string[]) => void;
|
|
96
|
+
|
|
97
|
+
// Way 2: Input rest parameter type by Object index.
|
|
98
|
+
type HandleLog2 = SetParameterType<HandleMessage, {2: string}>;
|
|
99
|
+
//=> type HandleLog2 = (data: Data, message: string, ...arguments: string[]) => void;
|
|
54
100
|
```
|
|
55
101
|
|
|
56
102
|
@category Function
|
|
@@ -62,7 +108,7 @@ export type SetParameterType<Fn extends (...arguments_: any[]) => unknown, P ext
|
|
|
62
108
|
// If a function did not specify the `this` fake parameter, it will be inferred to `unknown`.
|
|
63
109
|
// We want to detect this situation just to display a friendlier type upon hovering on an IntelliSense-powered IDE.
|
|
64
110
|
IsUnknown<ThisArg> extends true
|
|
65
|
-
? (...arguments_:
|
|
66
|
-
: (this: ThisArg, ...arguments_:
|
|
111
|
+
? (...arguments_: MergeObjectToArray<Arguments, P>) => ReturnType<Fn>
|
|
112
|
+
: (this: ThisArg, ...arguments_: MergeObjectToArray<Arguments, P>) => ReturnType<Fn>
|
|
67
113
|
)
|
|
68
114
|
: Fn; // This part should be unreachable
|
package/source/subtract.d.ts
CHANGED
|
@@ -34,33 +34,35 @@ Subtract<PositiveInfinity, PositiveInfinity>;
|
|
|
34
34
|
@category Numeric
|
|
35
35
|
*/
|
|
36
36
|
// TODO: Support big integer and negative number.
|
|
37
|
-
export type Subtract<A extends number, B extends number> =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
: Or<
|
|
47
|
-
And<IsEqual<R[1], true>, IsEqual<R[3], false>>,
|
|
48
|
-
And<IsEqual<R[2], true>, IsEqual<R[0], false>>
|
|
37
|
+
export type Subtract<A extends number, B extends number> = number extends A | B
|
|
38
|
+
? number
|
|
39
|
+
: [
|
|
40
|
+
IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>,
|
|
41
|
+
IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity>,
|
|
42
|
+
] extends infer R extends [boolean, boolean, boolean, boolean]
|
|
43
|
+
? Or<
|
|
44
|
+
And<IsEqual<R[0], true>, IsEqual<R[2], false>>,
|
|
45
|
+
And<IsEqual<R[3], true>, IsEqual<R[1], false>>
|
|
49
46
|
> extends true
|
|
50
|
-
?
|
|
51
|
-
:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
:
|
|
65
|
-
|
|
66
|
-
|
|
47
|
+
? PositiveInfinity
|
|
48
|
+
: Or<
|
|
49
|
+
And<IsEqual<R[1], true>, IsEqual<R[3], false>>,
|
|
50
|
+
And<IsEqual<R[2], true>, IsEqual<R[0], false>>
|
|
51
|
+
> extends true
|
|
52
|
+
? NegativeInfinity
|
|
53
|
+
: true extends R[number]
|
|
54
|
+
? number
|
|
55
|
+
: [IsNegative<A>, IsNegative<B>] extends infer R
|
|
56
|
+
? [false, false] extends R
|
|
57
|
+
? BuildTuple<A> extends infer R
|
|
58
|
+
? R extends [...BuildTuple<B>, ...infer R]
|
|
59
|
+
? R['length']
|
|
60
|
+
: number
|
|
61
|
+
: never
|
|
62
|
+
: LessThan<A, B> extends true
|
|
63
|
+
? number
|
|
64
|
+
: [false, true] extends R
|
|
65
|
+
? Sum<A, NumberAbsolute<B>>
|
|
66
|
+
: Subtract<NumberAbsolute<B>, NumberAbsolute<A>>
|
|
67
|
+
: never
|
|
68
|
+
: never;
|
package/source/sum.d.ts
CHANGED
|
@@ -34,33 +34,35 @@ Sum<PositiveInfinity, NegativeInfinity>;
|
|
|
34
34
|
@category Numeric
|
|
35
35
|
*/
|
|
36
36
|
// TODO: Support big integer and negative number.
|
|
37
|
-
export type Sum<A extends number, B extends number> =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
: Or<
|
|
47
|
-
And<IsEqual<R[1], true>, IsEqual<R[2], false>>,
|
|
48
|
-
And<IsEqual<R[3], true>, IsEqual<R[0], false>>
|
|
37
|
+
export type Sum<A extends number, B extends number> = number extends A | B
|
|
38
|
+
? number
|
|
39
|
+
: [
|
|
40
|
+
IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>,
|
|
41
|
+
IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity>,
|
|
42
|
+
] extends infer R extends [boolean, boolean, boolean, boolean]
|
|
43
|
+
? Or<
|
|
44
|
+
And<IsEqual<R[0], true>, IsEqual<R[3], false>>,
|
|
45
|
+
And<IsEqual<R[2], true>, IsEqual<R[1], false>>
|
|
49
46
|
> extends true
|
|
50
|
-
?
|
|
51
|
-
:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
? PositiveInfinity
|
|
48
|
+
: Or<
|
|
49
|
+
And<IsEqual<R[1], true>, IsEqual<R[2], false>>,
|
|
50
|
+
And<IsEqual<R[3], true>, IsEqual<R[0], false>>
|
|
51
|
+
> extends true
|
|
52
|
+
? NegativeInfinity
|
|
53
|
+
: true extends R[number]
|
|
54
|
+
? number
|
|
55
|
+
: ([IsNegative<A>, IsNegative<B>] extends infer R
|
|
56
|
+
? [false, false] extends R
|
|
57
|
+
? [...BuildTuple<A>, ...BuildTuple<B>]['length']
|
|
58
|
+
: [true, true] extends R
|
|
59
|
+
? number
|
|
60
|
+
: ArrayMax<[NumberAbsolute<A>, NumberAbsolute<B>]> extends infer Max_
|
|
61
|
+
? ArrayMin<[NumberAbsolute<A>, NumberAbsolute<B>]> extends infer Min_ extends number
|
|
62
|
+
? Max_ extends A | B
|
|
63
|
+
? Subtract<Max_, Min_>
|
|
64
|
+
: number
|
|
65
|
+
: never
|
|
63
66
|
: never
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
: never;
|
|
67
|
+
: never) & number
|
|
68
|
+
: never;
|