type-plus 4.8.0 → 4.9.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/cjs/math/Digit.d.ts +2 -0
- package/cjs/math/GreaterThan.d.ts +4 -4
- package/cjs/math/Max.d.ts +3 -10
- package/cjs/object/split.d.ts +1 -1
- package/package.json +1 -1
- package/ts/math/Digit.ts +2 -0
- package/ts/math/GreaterThan.spec.ts +75 -40
- package/ts/math/GreaterThan.ts +13 -14
- package/ts/math/Max.spec.ts +59 -35
- package/ts/math/Max.ts +6 -30
- package/ts/object/split.spec.ts +18 -0
- package/ts/object/split.ts +1 -1
package/README.md
CHANGED
|
@@ -415,8 +415,8 @@ So you may encounter some weird behavior if your logic is complex.
|
|
|
415
415
|
- `Abs<N, Fail=never>`: `Abs(N)`, `Abs<number>` returns `Fail`.
|
|
416
416
|
- `IsPositive<N>`: is `N` a positive number literal. `IsPositive<number>` returns `false`.
|
|
417
417
|
- `IsWhole<N>`: is `N` a whole number literal. `IsWhole<number>` returns `false`.
|
|
418
|
-
- `Max<A, B, Fail=never>`: `max(A, B)`, for
|
|
419
|
-
- `GreaterThan<A, B, Fail=never>`: `A > B` for
|
|
418
|
+
- `Max<A, B, Fail=never>`: `max(A, B)`, for whole number, `Fail` otherwise.
|
|
419
|
+
- `GreaterThan<A, B, Fail=never>`: `A > B` for whole numbers, `Fail` otherwise.
|
|
420
420
|
|
|
421
421
|
#### Arithmetics
|
|
422
422
|
|
package/cjs/math/Digit.d.ts
CHANGED
|
@@ -48,6 +48,8 @@ export declare namespace DigitArray {
|
|
|
48
48
|
type ToTuple<R extends any[], S extends number[], X = any> = S['length'] extends 0 ? R : (S['length'] extends 1 ? [...R, ...Digit.ToTuple<X>[S[0]]] : (S extends [any, ...infer T] ? (T extends any[] ? ToTuple<Multi10<[...R, ...Digit.ToTuple<X>[S[0]]]>, T> : never) : never));
|
|
49
49
|
type Multi10<C extends any[]> = [...C, ...C, ...C, ...C, ...C, ...C, ...C, ...C, ...C, ...C];
|
|
50
50
|
type FromNumber<N extends number> = FromString<NumberToString<N>>;
|
|
51
|
+
type FromNumberAbs<N extends number> = FromString<TrimMinusSign<`${N}`>>;
|
|
52
|
+
type TrimMinusSign<N extends string> = N extends `-${infer rest}` ? rest : N;
|
|
51
53
|
type NumberToString<N extends number> = (And<IsPositive<N>, IsWhole<N>>) extends true ? `${N}` : never;
|
|
52
54
|
type FromString<S extends string> = S extends `1${infer L}` ? [1, ...FromString<L>] : S extends `2${infer L}` ? [2, ...FromString<L>] : S extends `3${infer L}` ? [3, ...FromString<L>] : S extends `4${infer L}` ? [4, ...FromString<L>] : S extends `5${infer L}` ? [5, ...FromString<L>] : S extends `6${infer L}` ? [6, ...FromString<L>] : S extends `7${infer L}` ? [7, ...FromString<L>] : S extends `8${infer L}` ? [8, ...FromString<L>] : S extends `9${infer L}` ? [9, ...FromString<L>] : S extends `0${infer L}` ? [0, ...FromString<L>] : [];
|
|
53
55
|
type Shift10<DA extends number[]> = TrimLeadingZero<Shift10State<[], DA>>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Head, PadLeft, Tail } from '../array';
|
|
2
|
-
import type { And, Equal } from '../predicates';
|
|
2
|
+
import type { And, Equal, Or, Xor } from '../predicates';
|
|
3
3
|
import type { Digit, DigitArray } from './Digit';
|
|
4
4
|
import type { IsPositive } from './IsPositive';
|
|
5
5
|
import type { IsWhole } from './IsWhole';
|
|
6
6
|
import type { Max } from './Max';
|
|
7
|
-
export declare type GreaterThan<A extends number, B extends number, Fail = never> = And<
|
|
7
|
+
export declare type GreaterThan<A extends number, B extends number, Fail = never> = And<IsWhole<A>, IsWhole<B>> extends false ? Fail : number extends A ? Fail : number extends B ? Fail : Equal<A, B> extends true ? false : Xor<IsPositive<A>, IsPositive<B>> extends true ? IsPositive<A> : Or<IsPositive<A>, IsPositive<B>> extends false ? GreaterThan.ForWholeNumber<B, A> : GreaterThan.ForWholeNumber<A, B>;
|
|
8
8
|
export declare namespace GreaterThan {
|
|
9
|
-
type
|
|
10
|
-
type
|
|
9
|
+
type ForWholeNumber<A extends number, B extends number> = (DigitArray.FromNumberAbs<A> extends infer DA ? DA extends number[] ? DigitArray.FromNumberAbs<B> extends infer DB ? DB extends number[] ? Max<DA['length'], DB['length']> extends infer M ? M extends number ? PadLeft<DA, M, 0> extends infer PDA ? PDA extends number[] ? PadLeft<DB, M, 0> extends infer PDB ? PDB extends number[] ? ForDigitArray<PDA, PDB> : never : never : never : never : never : never : never : never : never : never);
|
|
10
|
+
type ForDigitArray<DA extends number[], DB extends number[]> = (Equal<Head<DA>, Head<DB>> extends true ? ForDigitArray<Tail<DA>, Tail<DB>> : Digit.GreaterThan<Head<DA>, Head<DB>>);
|
|
11
11
|
}
|
package/cjs/math/Max.d.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import type { IsPositive } from './IsPositive';
|
|
5
|
-
import type { IsWhole } from './IsWhole';
|
|
6
|
-
export declare type Max<A extends number, B extends number, Fail = never> = And<IsPositive<A>, IsWhole<A>> extends false ? Fail : And<IsPositive<B>, IsWhole<B>> extends false ? Fail : number extends A ? Fail : number extends B ? Fail : Equal<A, B> extends true ? A : Max.OnPositiveWhole<A, B>;
|
|
7
|
-
export declare namespace Max {
|
|
8
|
-
type OnPositiveWhole<A extends number, B extends number> = (DigitArray.FromNumber<A> extends infer DA ? DA extends number[] ? DigitArray.FromNumber<B> extends infer DB ? DB extends number[] ? OnDigitArray<DA, DB> extends DA ? A : B : never : never : never : never);
|
|
9
|
-
type OnDigitArray<DA extends number[], DB extends number[]> = Equal<DA['length'], DB['length']> extends true ? (Equal<Head<DA>, Head<DB>> extends true ? (Tail<DA> extends infer TDA ? TDA extends number[] ? OnDigitArray<TDA, Tail<DB>> extends TDA ? DA : DB : never : never) : Digit.GreaterThan<Head<DA>, Head<DB>> extends true ? DA : DB) : OnPositiveWhole<DA['length'], DB['length']> extends DA['length'] ? DA : DB;
|
|
10
|
-
}
|
|
1
|
+
import type { Equal } from '../predicates';
|
|
2
|
+
import { GreaterThan } from './GreaterThan';
|
|
3
|
+
export declare type Max<A extends number, B extends number, Fail = never> = GreaterThan<A, B> extends infer Result ? Equal<Result, never> extends true ? Fail : Result extends true ? A : B : never;
|
package/cjs/object/split.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ declare type Splitter<T extends AnyRecord> = Partial<{
|
|
|
4
4
|
[k in keyof T]: T[k] | undefined;
|
|
5
5
|
}>;
|
|
6
6
|
export declare type Split<T extends AnyRecord, S extends AnyRecord> = {
|
|
7
|
-
[k in keyof S]
|
|
7
|
+
[k in keyof S]-?: S[k] extends undefined ? T[k] : NonNullable<T[k]> | S[k];
|
|
8
8
|
};
|
|
9
9
|
export declare function split<T extends AnyRecord, S1 extends Splitter<T>>(target: T, split1: S1): [
|
|
10
10
|
Split<T, S1>,
|
package/package.json
CHANGED
package/ts/math/Digit.ts
CHANGED
|
@@ -66,6 +66,8 @@ export namespace DigitArray {
|
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
export type FromNumber<N extends number> = FromString<NumberToString<N>>
|
|
69
|
+
export type FromNumberAbs<N extends number> = FromString<TrimMinusSign<`${N}`>>
|
|
70
|
+
export type TrimMinusSign<N extends string> = N extends `-${infer rest}` ? rest : N
|
|
69
71
|
|
|
70
72
|
export type NumberToString<N extends number> = (And<IsPositive<N>, IsWhole<N>>) extends true ? `${N}` : never
|
|
71
73
|
|
|
@@ -1,40 +1,75 @@
|
|
|
1
|
-
import { GreaterThan, isType } from '..'
|
|
2
|
-
|
|
3
|
-
test('only support
|
|
4
|
-
isType.equal<true, never, GreaterThan<0.1, 1>>()
|
|
5
|
-
isType.equal<true, never, GreaterThan
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
isType.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
isType.
|
|
27
|
-
isType.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
isType.
|
|
31
|
-
isType.
|
|
32
|
-
isType.
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
test('with different number of digits', () => {
|
|
36
|
-
isType.
|
|
37
|
-
isType.
|
|
38
|
-
isType.
|
|
39
|
-
isType.
|
|
40
|
-
|
|
1
|
+
import { GreaterThan, isType } from '..'
|
|
2
|
+
|
|
3
|
+
test('only support whole number', () => {
|
|
4
|
+
isType.equal<true, never, GreaterThan<0.1, 1>>()
|
|
5
|
+
isType.equal<true, never, GreaterThan<1, 0.1>>()
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
test('number gets never', () => {
|
|
9
|
+
isType.equal<true, never, GreaterThan<number, 1>>()
|
|
10
|
+
isType.equal<true, never, GreaterThan<1, number>>()
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
test('override Fail case', () => {
|
|
14
|
+
isType.equal<true, number, GreaterThan<number, 2, number>>()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test('n > n is false', () => {
|
|
18
|
+
isType.equal<true, false, GreaterThan<0, 0>>()
|
|
19
|
+
isType.equal<true, false, GreaterThan<1, 1>>()
|
|
20
|
+
isType.equal<true, false, GreaterThan<12, 12>>()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test('with same number of digits', () => {
|
|
24
|
+
isType.equal<true, true, GreaterThan<1, 0>>()
|
|
25
|
+
isType.equal<true, true, GreaterThan<22, 11>>()
|
|
26
|
+
isType.equal<true, true, GreaterThan<20, 19>>()
|
|
27
|
+
isType.equal<true, true, GreaterThan<19, 10>>()
|
|
28
|
+
|
|
29
|
+
isType.equal<true, false, GreaterThan<0, 1>>()
|
|
30
|
+
isType.equal<true, false, GreaterThan<11, 22>>()
|
|
31
|
+
isType.equal<true, false, GreaterThan<19, 20>>()
|
|
32
|
+
isType.equal<true, false, GreaterThan<10, 19>>()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('with different number of digits', () => {
|
|
36
|
+
isType.equal<true, false, GreaterThan<0, 1>>()
|
|
37
|
+
isType.equal<true, false, GreaterThan<9, 100>>()
|
|
38
|
+
isType.equal<true, true, GreaterThan<10, 1>>()
|
|
39
|
+
isType.equal<true, true, GreaterThan<123, 32>>()
|
|
40
|
+
isType.equal<true, true, GreaterThan<123, 13>>()
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('-0 > 0 and 0 > -0 are false', () => {
|
|
44
|
+
isType.equal<true, false, GreaterThan<-0, 0>>()
|
|
45
|
+
isType.equal<true, false, GreaterThan<0, -0>>()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('works with negative numbers', () => {
|
|
49
|
+
isType.equal<true, true, GreaterThan<0, -1>>()
|
|
50
|
+
isType.equal<true, true, GreaterThan<1, -1>>()
|
|
51
|
+
isType.equal<true, true, GreaterThan<2, -1>>()
|
|
52
|
+
|
|
53
|
+
isType.equal<true, false, GreaterThan<-1, 0>>()
|
|
54
|
+
isType.equal<true, false, GreaterThan<-1, 1>>()
|
|
55
|
+
isType.equal<true, false, GreaterThan<-1, 2>>()
|
|
56
|
+
|
|
57
|
+
isType.equal<true, false, GreaterThan<-0, -0>>()
|
|
58
|
+
isType.equal<true, false, GreaterThan<-1, -1>>()
|
|
59
|
+
|
|
60
|
+
isType.equal<true, true, GreaterThan<-0, -1>>()
|
|
61
|
+
isType.equal<true, false, GreaterThan<-1, -1>>()
|
|
62
|
+
isType.equal<true, false, GreaterThan<-2, -1>>()
|
|
63
|
+
|
|
64
|
+
isType.equal<true, false, GreaterThan<-1, -0>>()
|
|
65
|
+
isType.equal<true, false, GreaterThan<-1, -1>>()
|
|
66
|
+
isType.equal<true, true, GreaterThan<-1, -2>>()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('work with large numbers', () => {
|
|
70
|
+
isType.equal<true, true, GreaterThan<1000000, 0>>()
|
|
71
|
+
isType.equal<true, false, GreaterThan<0, 1000000>>()
|
|
72
|
+
|
|
73
|
+
isType.equal<true, false, GreaterThan<-1000000, 0>>()
|
|
74
|
+
isType.equal<true, true, GreaterThan<0, -1000000>>()
|
|
75
|
+
})
|
package/ts/math/GreaterThan.ts
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
import type { Head, PadLeft, Tail } from '../array'
|
|
2
|
-
import type { And, Equal } from '../predicates'
|
|
2
|
+
import type { And, Equal, Or, Xor } from '../predicates'
|
|
3
3
|
import type { Digit, DigitArray } from './Digit'
|
|
4
4
|
import type { IsPositive } from './IsPositive'
|
|
5
5
|
import type { IsWhole } from './IsWhole'
|
|
6
6
|
import type { Max } from './Max'
|
|
7
7
|
|
|
8
8
|
export type GreaterThan<A extends number, B extends number, Fail = never> =
|
|
9
|
-
And<
|
|
10
|
-
And<IsPositive<A>, IsWhole<A>>,
|
|
11
|
-
And<IsPositive<B>, IsWhole<B>>
|
|
12
|
-
> extends false ? Fail :
|
|
9
|
+
And<IsWhole<A>, IsWhole<B>> extends false ? Fail :
|
|
13
10
|
number extends A ? Fail :
|
|
14
11
|
number extends B ? Fail :
|
|
15
12
|
Equal<A, B> extends true ? false :
|
|
16
|
-
|
|
13
|
+
Xor<IsPositive<A>, IsPositive<B>> extends true ? IsPositive<A> :
|
|
14
|
+
Or<IsPositive<A>, IsPositive<B>> extends false ? GreaterThan.ForWholeNumber<B, A> :
|
|
15
|
+
GreaterThan.ForWholeNumber<A, B>
|
|
17
16
|
|
|
18
17
|
export namespace GreaterThan {
|
|
19
|
-
export type
|
|
20
|
-
DigitArray.
|
|
21
|
-
DigitArray.
|
|
18
|
+
export type ForWholeNumber<A extends number, B extends number> = (
|
|
19
|
+
DigitArray.FromNumberAbs<A> extends infer DA ? DA extends number[] ?
|
|
20
|
+
DigitArray.FromNumberAbs<B> extends infer DB ? DB extends number[] ?
|
|
22
21
|
Max<DA['length'], DB['length']> extends infer M ? M extends number ?
|
|
23
22
|
PadLeft<DA, M, 0> extends infer PDA ? PDA extends number[] ?
|
|
24
23
|
PadLeft<DB, M, 0> extends infer PDB ? PDB extends number[] ?
|
|
25
|
-
|
|
24
|
+
ForDigitArray<PDA, PDB>
|
|
26
25
|
: never : never
|
|
27
26
|
: never : never
|
|
28
27
|
: never : never
|
|
@@ -30,9 +29,9 @@ export namespace GreaterThan {
|
|
|
30
29
|
: never : never
|
|
31
30
|
)
|
|
32
31
|
|
|
33
|
-
export type
|
|
34
|
-
Equal<Head<DA>, Head<DB>> extends true
|
|
35
|
-
|
|
36
|
-
Digit.GreaterThan<Head<DA>, Head<DB>>
|
|
32
|
+
export type ForDigitArray<DA extends number[], DB extends number[]> = (
|
|
33
|
+
Equal<Head<DA>, Head<DB>> extends true
|
|
34
|
+
? ForDigitArray<Tail<DA>, Tail<DB>>
|
|
35
|
+
: Digit.GreaterThan<Head<DA>, Head<DB>>
|
|
37
36
|
)
|
|
38
37
|
}
|
package/ts/math/Max.spec.ts
CHANGED
|
@@ -1,35 +1,59 @@
|
|
|
1
|
-
import { isType, Max } from '..'
|
|
2
|
-
|
|
3
|
-
test('only support
|
|
4
|
-
isType.equal<true, never, Max<0.1, 1>>()
|
|
5
|
-
isType.equal<true, never, Max
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
isType.equal<true,
|
|
25
|
-
isType.equal<true,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
isType.equal<true,
|
|
32
|
-
isType.equal<true,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
1
|
+
import { isType, Max } from '..'
|
|
2
|
+
|
|
3
|
+
test('only support whole number', () => {
|
|
4
|
+
isType.equal<true, never, Max<0.1, 1>>()
|
|
5
|
+
isType.equal<true, never, Max<1, 0.1>>()
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
test('number gets never', () => {
|
|
9
|
+
isType.equal<true, never, Max<number, 1>>()
|
|
10
|
+
isType.equal<true, never, Max<1, number>>()
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
test('override Fail case', () => {
|
|
14
|
+
isType.equal<true, number, Max<number, 1, number>>()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test('same number', () => {
|
|
18
|
+
isType.equal<true, 123, Max<123, 123>>()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('same number of digits', () => {
|
|
22
|
+
isType.equal<true, 124, Max<123, 124>>()
|
|
23
|
+
isType.equal<true, 126, Max<126, 124>>()
|
|
24
|
+
isType.equal<true, 224, Max<126, 224>>()
|
|
25
|
+
isType.equal<true, 726, Max<726, 224>>()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('more digits win', () => {
|
|
29
|
+
isType.equal<true, 123, Max<123, 22>>()
|
|
30
|
+
isType.equal<true, 223, Max<12, 223>>()
|
|
31
|
+
isType.equal<true, 1234567891011, Max<1234567891011, 123>>()
|
|
32
|
+
isType.equal<true, 1234567891011, Max<123, 1234567891011>>()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('work with negative numbers', () => {
|
|
36
|
+
isType.equal<true, 0, Max<0, -0>>()
|
|
37
|
+
isType.equal<true, 0, Max<-0, 0>>()
|
|
38
|
+
isType.equal<true, 0, Max<-0, -0>>()
|
|
39
|
+
|
|
40
|
+
isType.equal<true, 0, Max<0, -1>>()
|
|
41
|
+
isType.equal<true, 1, Max<1, -1>>()
|
|
42
|
+
isType.equal<true, 2, Max<2, -1>>()
|
|
43
|
+
|
|
44
|
+
isType.equal<true, 0, Max<-1, 0>>()
|
|
45
|
+
isType.equal<true, 1, Max<-1, 1>>()
|
|
46
|
+
isType.equal<true, 2, Max<-1, 2>>()
|
|
47
|
+
|
|
48
|
+
isType.equal<true, -1, Max<-1, -2>>()
|
|
49
|
+
isType.equal<true, -2, Max<-2, -2>>()
|
|
50
|
+
isType.equal<true, -2, Max<-3, -2>>()
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('work with large numbers', () => {
|
|
54
|
+
isType.equal<true, 1000000, Max<1000000, 0>>()
|
|
55
|
+
isType.equal<true, 1000000, Max<0, 1000000>>()
|
|
56
|
+
|
|
57
|
+
isType.equal<true, 0, Max<-1000000, 0>>()
|
|
58
|
+
isType.equal<true, 0, Max<0, -1000000>>()
|
|
59
|
+
})
|
package/ts/math/Max.ts
CHANGED
|
@@ -1,32 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
3
|
-
import type { Digit, DigitArray } from './Digit'
|
|
4
|
-
import type { IsPositive } from './IsPositive'
|
|
5
|
-
import type { IsWhole } from './IsWhole'
|
|
1
|
+
import type { Equal } from '../predicates'
|
|
2
|
+
import { GreaterThan } from './GreaterThan'
|
|
6
3
|
|
|
7
4
|
export type Max<A extends number, B extends number, Fail = never> =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Equal<A, B> extends true ? A :
|
|
13
|
-
Max.OnPositiveWhole<A, B>
|
|
14
|
-
|
|
15
|
-
export namespace Max {
|
|
16
|
-
export type OnPositiveWhole<A extends number, B extends number> = (
|
|
17
|
-
DigitArray.FromNumber<A> extends infer DA ? DA extends number[] ?
|
|
18
|
-
DigitArray.FromNumber<B> extends infer DB ? DB extends number[] ?
|
|
19
|
-
OnDigitArray<DA, DB> extends DA ? A : B
|
|
20
|
-
: never : never
|
|
21
|
-
: never : never
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
export type OnDigitArray<DA extends number[], DB extends number[]> =
|
|
25
|
-
Equal<DA['length'], DB['length']> extends true
|
|
26
|
-
? (Equal<Head<DA>, Head<DB>> extends true
|
|
27
|
-
? (Tail<DA> extends infer TDA ? TDA extends number[] ?
|
|
28
|
-
OnDigitArray<TDA, Tail<DB>> extends TDA ? DA : DB
|
|
29
|
-
: never : never)
|
|
30
|
-
: Digit.GreaterThan<Head<DA>, Head<DB>> extends true ? DA : DB)
|
|
31
|
-
: OnPositiveWhole<DA['length'], DB['length']> extends DA['length'] ? DA : DB
|
|
32
|
-
}
|
|
5
|
+
GreaterThan<A, B> extends infer Result ?
|
|
6
|
+
Equal<Result, never> extends true ? Fail :
|
|
7
|
+
Result extends true ? A : B
|
|
8
|
+
: never
|
package/ts/object/split.spec.ts
CHANGED
|
@@ -35,6 +35,24 @@ test('can default with null', () => {
|
|
|
35
35
|
isType.equal<true, number | null, typeof a>()
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
+
test('remove optional/undefined when default is provided', () => {
|
|
39
|
+
interface S {
|
|
40
|
+
variant?: 'abc' | 'def'
|
|
41
|
+
}
|
|
42
|
+
const s: S = {}
|
|
43
|
+
const [a] = split(s, { variant: 'def' })
|
|
44
|
+
isType.equal<true, 'abc' | 'def', typeof a.variant>()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('keep undefined when default is undefined', () => {
|
|
48
|
+
interface S {
|
|
49
|
+
variant?: 'abc' | 'def'
|
|
50
|
+
}
|
|
51
|
+
const s: S = {}
|
|
52
|
+
const [a] = split(s, { variant: undefined })
|
|
53
|
+
isType.equal<true, 'abc' | 'def' | undefined, typeof a.variant>()
|
|
54
|
+
})
|
|
55
|
+
|
|
38
56
|
|
|
39
57
|
test('can default with false', () => {
|
|
40
58
|
const s: { a?: number | boolean } = {}
|
package/ts/object/split.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { reduceByKey } from './reduceKey'
|
|
|
4
4
|
|
|
5
5
|
type Splitter<T extends AnyRecord> = Partial<{ [k in keyof T]: T[k] | undefined }>
|
|
6
6
|
export type Split<T extends AnyRecord, S extends AnyRecord> = {
|
|
7
|
-
[k in keyof S]
|
|
7
|
+
[k in keyof S]-?: S[k] extends undefined ? T[k] : NonNullable<T[k]> | S[k]
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
/**
|