type-plus 4.5.1 → 4.6.1
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 +3 -1
- package/cjs/array/CreateTuple.d.ts +2 -5
- package/cjs/array/DropMatch.d.ts +5 -0
- package/cjs/array/DropMatch.js +3 -0
- package/cjs/array/DropMatch.js.map +1 -0
- package/cjs/array/Filter.d.ts +1 -0
- package/cjs/array/index.d.ts +2 -1
- package/cjs/array/index.js.map +1 -1
- package/cjs/math/Digit.d.ts +21 -21
- package/esm/array/DropMatch.js +2 -0
- package/esm/array/DropMatch.js.map +1 -0
- package/esm/array/index.js.map +1 -1
- package/package.json +1 -1
- package/ts/array/CreateTuple.spec.ts +34 -21
- package/ts/array/CreateTuple.ts +7 -7
- package/ts/array/DropMatch.spec.ts +113 -0
- package/ts/array/DropMatch.ts +53 -0
- package/ts/array/Filter.spec.ts +54 -1
- package/ts/array/Filter.ts +9 -0
- package/ts/array/index.ts +2 -1
- package/ts/math/Add.spec.ts +82 -82
- package/ts/math/Digit.spec.ts +184 -185
- package/ts/math/Digit.ts +23 -23
package/README.md
CHANGED
|
@@ -285,12 +285,14 @@ type No = IsAny<1, 'yes', 'no'> // 'no'
|
|
|
285
285
|
- `CreateTuple<L, T>`: Creates `Tuple<T>` with `L` number of elements.
|
|
286
286
|
- `DropFirst<A>`: drops the first value type of `A`.
|
|
287
287
|
- `DropLast<A>`: drops the last value type of `A`.
|
|
288
|
-
- `
|
|
288
|
+
- `DropMatch<A, Criteria>`: drops entries matching `Criteria` in array or tuple `A`.
|
|
289
|
+
- `Filter<A, Criteria>`: filter the array or tuple `A`, keeping entries satisfying `Criteria`. **deprecated. Renaming to `KeepMatch`**
|
|
289
290
|
- `FindFirst<A, Criteria>`: gets the first type satisfying `Criteria`.
|
|
290
291
|
- `FindLast<A, Criteria>`: gets the last type satisfying `Criteria`.
|
|
291
292
|
- `Head<A>`: gets the first entry in the array.
|
|
292
293
|
- `IntersectOfProps<A, K>`: gets the intersect of `A[K]` types (deprecate `MapToProp`)
|
|
293
294
|
- `IsArray<T>`: `logical` predicate for `Array`.
|
|
295
|
+
- `KeepMatch<A, Criteria>`: keeps entries satisfying `Criteria` in array or tuple `A`.
|
|
294
296
|
- `Last<A>`: gets the last type of an array or tuple.
|
|
295
297
|
- `literalArray(...entries)`: return an array whose items are restricted to the provided literals.
|
|
296
298
|
- `PadLeft<A, Total, PadWith>`: pads `A` with `PadWith` if the length of `A` is less than `L`.
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
export declare type CreateTuple<L extends number, T = any> = IsPositive<L> extends true ?
|
|
3
|
-
export declare namespace CreateTuple {
|
|
4
|
-
type Device<R extends any[], L extends number, T> = R['length'] extends L ? R : Device<[T, ...R], L, T>;
|
|
5
|
-
}
|
|
1
|
+
import { DigitArray, IsPositive } from '../math';
|
|
2
|
+
export declare type CreateTuple<L extends number, T = any> = number extends L ? T[] : IsPositive<L> extends true ? DigitArray.ToTuple<[], DigitArray.FromNumber<L>, T> : never;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Equal } from '../predicates';
|
|
2
|
+
declare type ExcludeUnionOfEmptyTuple<A> = Equal<A, []> extends true ? A : Exclude<A, []>;
|
|
3
|
+
export declare type DropMatch<A extends Array<any>, Criteria> = number extends A['length'] ? (A[0] extends Criteria ? never[] : (undefined extends Criteria ? Array<NonNullable<A[0]>> : (Criteria extends A[0] ? Array<Exclude<A[0], Criteria>> : A))) : DropMatchTuple<A, Criteria>;
|
|
4
|
+
declare type DropMatchTuple<A extends Array<any>, Criteria> = (A['length'] extends 0 ? A : (A extends [infer Head, ...infer Tail] ? (Tail['length'] extends 0 ? (undefined extends Criteria ? (Head extends Criteria ? [] : [Head]) : ExcludeUnionOfEmptyTuple<(Head extends Criteria ? [] : [Head])>) : (Exclude<Head, Criteria> extends never ? DropMatch<Tail, Criteria> : [Exclude<Head, Criteria>, ...DropMatch<Tail, Criteria>])) : never[]));
|
|
5
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropMatch.js","sourceRoot":"","sources":["../../ts/array/DropMatch.ts"],"names":[],"mappings":""}
|
package/cjs/array/Filter.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
1
|
export declare type Filter<A extends Array<any>, Criteria> = number extends A['length'] ? (A[0] extends Criteria ? A : (Criteria extends A[0] ? Array<Criteria> : never[])) : (A['length'] extends 0 ? never : (A extends [infer Head, ...infer Tail] ? (Tail['length'] extends 0 ? (Head extends Criteria ? [Head] : never[]) : (Head extends Criteria ? [Head, ...Filter<Tail, Criteria>] : Filter<Tail, Criteria>)) : never));
|
|
2
|
+
export declare type KeepMatch<A extends Array<any>, Criteria> = Filter<A, Criteria>;
|
package/cjs/array/index.d.ts
CHANGED
|
@@ -3,7 +3,8 @@ export type { Concat } from './Concat';
|
|
|
3
3
|
export type { CreateTuple } from './CreateTuple';
|
|
4
4
|
export type { DropFirst } from './DropFirst';
|
|
5
5
|
export type { DropLast } from './DropLast';
|
|
6
|
-
export type {
|
|
6
|
+
export type { DropMatch } from './DropMatch';
|
|
7
|
+
export type { Filter, KeepMatch } from './Filter';
|
|
7
8
|
export type { FindFirst, First } from './FindFirst';
|
|
8
9
|
export type { FindLast } from './FindLast';
|
|
9
10
|
export type { Head } from './Head';
|
package/cjs/array/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/array/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/array/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAaA,iDAA8B;AAE9B,gDAA6B"}
|
package/cjs/math/Digit.d.ts
CHANGED
|
@@ -3,29 +3,29 @@ import { And } from '../predicates';
|
|
|
3
3
|
import { IsPositive } from './IsPositive';
|
|
4
4
|
import { IsWhole } from './IsWhole';
|
|
5
5
|
export declare namespace Digit {
|
|
6
|
-
type ToTuple = {
|
|
6
|
+
type ToTuple<T = 1> = {
|
|
7
7
|
[k in number]: any[];
|
|
8
8
|
} & {
|
|
9
9
|
0: [];
|
|
10
|
-
1: [
|
|
11
|
-
2: [
|
|
12
|
-
3: [
|
|
13
|
-
4: [
|
|
14
|
-
5: [
|
|
15
|
-
6: [
|
|
16
|
-
7: [
|
|
17
|
-
8: [
|
|
18
|
-
9: [
|
|
19
|
-
10: [
|
|
20
|
-
11: [
|
|
21
|
-
12: [
|
|
22
|
-
13: [
|
|
23
|
-
14: [
|
|
24
|
-
15: [
|
|
25
|
-
16: [
|
|
26
|
-
17: [
|
|
27
|
-
18: [
|
|
28
|
-
19: [
|
|
10
|
+
1: [T];
|
|
11
|
+
2: [T, T];
|
|
12
|
+
3: [T, T, T];
|
|
13
|
+
4: [T, T, T, T];
|
|
14
|
+
5: [T, T, T, T, T];
|
|
15
|
+
6: [T, T, T, T, T, T];
|
|
16
|
+
7: [T, T, T, T, T, T, T];
|
|
17
|
+
8: [T, T, T, T, T, T, T, T];
|
|
18
|
+
9: [T, T, T, T, T, T, T, T, T];
|
|
19
|
+
10: [T, T, T, T, T, T, T, T, T, T];
|
|
20
|
+
11: [T, T, T, T, T, T, T, T, T, T, T];
|
|
21
|
+
12: [T, T, T, T, T, T, T, T, T, T, T, T];
|
|
22
|
+
13: [T, T, T, T, T, T, T, T, T, T, T, T, T];
|
|
23
|
+
14: [T, T, T, T, T, T, T, T, T, T, T, T, T, T];
|
|
24
|
+
15: [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T];
|
|
25
|
+
16: [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T];
|
|
26
|
+
17: [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T];
|
|
27
|
+
18: [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T];
|
|
28
|
+
19: [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T];
|
|
29
29
|
};
|
|
30
30
|
type GreaterThan<A extends number, B extends number> = B extends GreaterThanMap[A] ? true : false;
|
|
31
31
|
type GreaterThanMap = {
|
|
@@ -45,7 +45,7 @@ export declare namespace Digit {
|
|
|
45
45
|
}
|
|
46
46
|
export declare namespace DigitArray {
|
|
47
47
|
type ToNumber<C extends number[]> = ToTuple<[], C>['length'];
|
|
48
|
-
type ToTuple<R extends any[], S extends number[]> = S['length'] extends 0 ? R : (S['length'] extends 1 ? [...R, ...Digit.ToTuple[S[0]]] : (S extends [any, ...infer T] ? (T extends any[] ? ToTuple<Multi10<[...R, ...Digit.ToTuple[S[0]]]>, T> : never) : never));
|
|
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
51
|
type NumberToString<N extends number> = (And<IsPositive<N>, IsWhole<N>>) extends true ? `${N}` : never;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropMatch.js","sourceRoot":"","sources":["../../ts/array/DropMatch.ts"],"names":[],"mappings":""}
|
package/esm/array/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/array/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/array/index.ts"],"names":[],"mappings":"AAaA,cAAc,gBAAgB,CAAA;AAE9B,cAAc,eAAe,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,21 +1,34 @@
|
|
|
1
|
-
import { CreateTuple, isType } from '..'
|
|
2
|
-
|
|
3
|
-
test('create empty tuple', () => {
|
|
4
|
-
isType.equal<true, [], CreateTuple<0>>()
|
|
5
|
-
})
|
|
6
|
-
|
|
7
|
-
test('single element', () => {
|
|
8
|
-
isType.equal<true, [any], CreateTuple<1>>()
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
test('multiple elements', () => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
import { CreateTuple, isType } from '..'
|
|
2
|
+
|
|
3
|
+
test('create empty tuple', () => {
|
|
4
|
+
isType.equal<true, [], CreateTuple<0>>()
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
test('single element', () => {
|
|
8
|
+
isType.equal<true, [any], CreateTuple<1>>()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
test('multiple elements', () => {
|
|
12
|
+
type A = CreateTuple<3>
|
|
13
|
+
isType.equal<true, [any, any, any], A>()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
test('override element type', () => {
|
|
17
|
+
type A = CreateTuple<5, 1>
|
|
18
|
+
isType.equal<true, [1, 1, 1, 1, 1], A>()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('negative length gets never', () => {
|
|
22
|
+
isType.equal<true, never, CreateTuple<-1>>()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('Can create tuple up to 7000', () => {
|
|
26
|
+
type A = CreateTuple<7000>['length']
|
|
27
|
+
|
|
28
|
+
isType.equal<true, 7000, A>()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('L = number gets array', () => {
|
|
32
|
+
type A = CreateTuple<number, 1>
|
|
33
|
+
isType.equal<true, 1[], A>()
|
|
34
|
+
})
|
package/ts/array/CreateTuple.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { DigitArray, IsPositive } from '../math'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Creates `Tuple<T>` with `L` number of elements.
|
|
5
|
+
* @note Other cool implementations by @lazytype, @jcalz:
|
|
6
|
+
* @see https://github.com/microsoft/TypeScript/issues/26223#issuecomment-674514787
|
|
7
|
+
* @see https://github.com/microsoft/TypeScript/issues/47874#issuecomment-1039157322
|
|
5
8
|
*/
|
|
6
9
|
export type CreateTuple<L extends number, T = any> =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export type Device<R extends any[], L extends number, T> =
|
|
11
|
-
R['length'] extends L ? R : Device<[T, ...R], L, T>
|
|
12
|
-
}
|
|
10
|
+
number extends L ? T[] : IsPositive<L> extends true
|
|
11
|
+
? DigitArray.ToTuple<[], DigitArray.FromNumber<L>, T>
|
|
12
|
+
: never
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { DropMatch, isType } from '..'
|
|
2
|
+
|
|
3
|
+
describe('DropMatch<A, C>', () => {
|
|
4
|
+
describe('A is array', () => {
|
|
5
|
+
test('drop all types gets never[]', () => {
|
|
6
|
+
type A = DropMatch<Array<string>, string>
|
|
7
|
+
isType.equal<true, never[], A>()
|
|
8
|
+
|
|
9
|
+
type B = DropMatch<Array<string | boolean>, string | boolean>
|
|
10
|
+
isType.equal<true, never[], B>()
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
test('drop undefined and null from array', () => {
|
|
14
|
+
type A = DropMatch<Array<string | undefined>, undefined>
|
|
15
|
+
isType.equal<true, string[], A>()
|
|
16
|
+
|
|
17
|
+
type B = DropMatch<Array<string | number | undefined>, undefined>
|
|
18
|
+
isType.equal<true, Array<string | number>, B>()
|
|
19
|
+
|
|
20
|
+
type C = DropMatch<Array<string | number | undefined | null>, undefined | null>
|
|
21
|
+
isType.equal<true, Array<string | number>, C>()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('can get undefined and null array when other types dropped', () => {
|
|
25
|
+
type A = DropMatch<Array<string | undefined>, string>
|
|
26
|
+
isType.equal<true, undefined[], A>()
|
|
27
|
+
|
|
28
|
+
type B = DropMatch<Array<string | number | null>, string>
|
|
29
|
+
isType.equal<true, Array<number | null>, B>()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('unmatched criteria returns original', () => {
|
|
33
|
+
type Actual = DropMatch<Array<string | undefined>, number>
|
|
34
|
+
|
|
35
|
+
isType.equal<true, Array<string | undefined>, Actual>()
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
describe('A is Tuple', () => {
|
|
40
|
+
test('empty tuple', () => {
|
|
41
|
+
type A = DropMatch<[], undefined>
|
|
42
|
+
isType.equal<true, [], A>()
|
|
43
|
+
|
|
44
|
+
type B = DropMatch<[1, undefined], undefined>
|
|
45
|
+
isType.equal<true, [1], B>()
|
|
46
|
+
|
|
47
|
+
type C = DropMatch<[1, undefined, 3], undefined>
|
|
48
|
+
isType.equal<true, [1, 3], C>()
|
|
49
|
+
|
|
50
|
+
type D = DropMatch<[1, string | undefined, 3], undefined>
|
|
51
|
+
isType.equal<true, [1, string, 3], D>()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('drop undefined from tuple', () => {
|
|
55
|
+
type A = DropMatch<[undefined], undefined>
|
|
56
|
+
isType.equal<true, [], A>()
|
|
57
|
+
|
|
58
|
+
type B = DropMatch<[1, undefined], undefined>
|
|
59
|
+
isType.equal<true, [1], B>()
|
|
60
|
+
|
|
61
|
+
type C = DropMatch<[1, undefined, 3], undefined>
|
|
62
|
+
isType.equal<true, [1, 3], C>()
|
|
63
|
+
|
|
64
|
+
type D = DropMatch<[1, string | undefined, 3], undefined>
|
|
65
|
+
isType.equal<true, [1, string, 3], D>()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('get original if not matched', () => {
|
|
69
|
+
type A = DropMatch<[1], undefined>
|
|
70
|
+
isType.equal<true, [1], A>()
|
|
71
|
+
|
|
72
|
+
type B = DropMatch<[1], undefined | string>
|
|
73
|
+
isType.equal<true, [1], B>()
|
|
74
|
+
|
|
75
|
+
type C = DropMatch<[1, 2, 3, 4], 5>
|
|
76
|
+
isType.equal<true, [1, 2, 3, 4], C>()
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('drop narrow type', () => {
|
|
80
|
+
type C = DropMatch<[1], number>
|
|
81
|
+
isType.equal<true, [], C>()
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('keep widen type', () => {
|
|
85
|
+
type D = DropMatch<[number], 1>
|
|
86
|
+
isType.equal<true, [number], D>()
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('drop type from tuple', () => {
|
|
90
|
+
type A = DropMatch<[1], 1>
|
|
91
|
+
isType.equal<true, [], A>()
|
|
92
|
+
|
|
93
|
+
type B = DropMatch<[number | string], number>
|
|
94
|
+
isType.equal<true, [string], B>()
|
|
95
|
+
|
|
96
|
+
type C = DropMatch<[1, undefined, 3], 1>
|
|
97
|
+
isType.equal<true, [undefined, 3], C>()
|
|
98
|
+
|
|
99
|
+
type D = DropMatch<[1, string | undefined, 3], 3>
|
|
100
|
+
isType.equal<true, [1, string | undefined], D>()
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
test('drop multiple types', () => {
|
|
104
|
+
type Actual = DropMatch<[1, 2, 3, 4], 2 | 4>
|
|
105
|
+
isType.equal<true, [1, 3], Actual>()
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
test('drop undefined and null', () => {
|
|
109
|
+
type Actual = DropMatch<[1, undefined, 3, null], undefined | null>
|
|
110
|
+
isType.equal<true, [1, 3], Actual>()
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Equal } from '../predicates'
|
|
2
|
+
|
|
3
|
+
type ExcludeUnionOfEmptyTuple<A> = Equal<A, []> extends true ? A : Exclude<A, []>
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* drops entries matching `Criteria` in array or tuple `A`.
|
|
7
|
+
*/
|
|
8
|
+
export type DropMatch<A extends Array<any>, Criteria> =
|
|
9
|
+
number extends A['length']
|
|
10
|
+
// array
|
|
11
|
+
? (A[0] extends Criteria
|
|
12
|
+
// criteria matches: DropAll<string[], string>
|
|
13
|
+
? never[]
|
|
14
|
+
: (undefined extends Criteria
|
|
15
|
+
? Array<NonNullable<A[0]>>
|
|
16
|
+
// TODO: A[0] extends Criteria?
|
|
17
|
+
: (Criteria extends A[0] ? Array<Exclude<A[0], Criteria>> : A))
|
|
18
|
+
)
|
|
19
|
+
: DropMatchTuple<A, Criteria>
|
|
20
|
+
|
|
21
|
+
type DropMatchTuple<A extends Array<any>, Criteria> =
|
|
22
|
+
(A['length'] extends 0
|
|
23
|
+
// empty tuple
|
|
24
|
+
? A
|
|
25
|
+
: (A extends [infer Head, ...infer Tail]
|
|
26
|
+
? (Tail['length'] extends 0
|
|
27
|
+
// single element tuple
|
|
28
|
+
? (undefined extends Criteria
|
|
29
|
+
? (Head extends Criteria
|
|
30
|
+
? []
|
|
31
|
+
: [Head])
|
|
32
|
+
: ExcludeUnionOfEmptyTuple<(Head extends Criteria ? [] : [Head])>
|
|
33
|
+
)
|
|
34
|
+
// multiple elements
|
|
35
|
+
: (Exclude<Head, Criteria> extends never
|
|
36
|
+
? DropMatch<Tail, Criteria>
|
|
37
|
+
: [Exclude<Head, Criteria>, ...DropMatch<Tail, Criteria>]
|
|
38
|
+
))
|
|
39
|
+
: never[]))
|
|
40
|
+
// : (undefined extends Criteria
|
|
41
|
+
// ? (Head extends undefined
|
|
42
|
+
// ? DropAll<Tail, Criteria>
|
|
43
|
+
// : [NonNullable<Head>, ...DropAll<Tail, Criteria>])
|
|
44
|
+
// : []
|
|
45
|
+
// ))
|
|
46
|
+
// : (Head extends Criteria
|
|
47
|
+
// ? (undefined extends Criteria
|
|
48
|
+
// ? [1, 2, 3]// [NonNullable<Head>, ...Filter<Tail, Criteria>]
|
|
49
|
+
// : [2, 3]// [Head, ...Filter<Tail, Criteria>]
|
|
50
|
+
// )
|
|
51
|
+
// : [2]//Filter<Tail, Criteria>
|
|
52
|
+
// ))
|
|
53
|
+
// : 2[]))
|
package/ts/array/Filter.spec.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Filter, isType } from '..'
|
|
1
|
+
import { Filter, isType, KeepMatch } from '..'
|
|
2
2
|
|
|
3
3
|
describe('Filter<A, C>', () => {
|
|
4
4
|
describe('A is array', () => {
|
|
@@ -52,3 +52,56 @@ describe('Filter<A, C>', () => {
|
|
|
52
52
|
})
|
|
53
53
|
})
|
|
54
54
|
})
|
|
55
|
+
|
|
56
|
+
describe('KeepMatch<A, C>', () => {
|
|
57
|
+
describe('A is array', () => {
|
|
58
|
+
test('array matching criteria gets itself', () => {
|
|
59
|
+
type Actual = KeepMatch<string[], string>
|
|
60
|
+
isType.equal<true, string[], Actual>()
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('array not matching criteria gets never[]', () => {
|
|
64
|
+
type Actual = KeepMatch<string[], number>
|
|
65
|
+
isType.equal<true, never[], Actual>()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('remove unmatched type form array', () => {
|
|
69
|
+
type Actual = KeepMatch<Array<string | number>, string>
|
|
70
|
+
|
|
71
|
+
isType.equal<true, string[], Actual>()
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
test('remove undefined and null', () => {
|
|
75
|
+
type Actual = KeepMatch<Array<string | undefined | null>, string>
|
|
76
|
+
isType.equal<true, string[], Actual>()
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('can filter with undefined and null', () => {
|
|
80
|
+
type Actual = KeepMatch<Array<string | undefined | null>, undefined | null>
|
|
81
|
+
// Array<undefined | null> is destructured to undefined[] | null[] by TypeScript
|
|
82
|
+
isType.equal<true, undefined[] | null[], Actual>()
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('work with never[]', () => {
|
|
86
|
+
type Actual = KeepMatch<never[], undefined>
|
|
87
|
+
isType.equal<true, never[], Actual>()
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
describe(`A is Tuple`, () => {
|
|
92
|
+
test('matching criteria', () => {
|
|
93
|
+
type Actual = KeepMatch<[1, 2, 3, 4], 2 | 4>
|
|
94
|
+
isType.equal<true, [2, 4], Actual>()
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
test('no match gets never[]', () => {
|
|
98
|
+
type Actual = KeepMatch<[1, 2, 3, 4], 5>
|
|
99
|
+
isType.equal<true, never[], Actual>()
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
test('matching undefined and null', () => {
|
|
103
|
+
type Actual = KeepMatch<[1, undefined, 3, null], undefined | null>
|
|
104
|
+
isType.equal<true, [undefined, null], Actual>()
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
})
|
package/ts/array/Filter.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* filter the array or tuple `A`, keeping entries satisfying `Criteria`.
|
|
3
|
+
* @deprecated renaming to `KeepMatch`
|
|
4
|
+
*/
|
|
1
5
|
export type Filter<A extends Array<any>, Criteria> =
|
|
2
6
|
number extends A['length']
|
|
3
7
|
// array
|
|
@@ -15,3 +19,8 @@ export type Filter<A extends Array<any>, Criteria> =
|
|
|
15
19
|
? [Head, ...Filter<Tail, Criteria>]
|
|
16
20
|
: Filter<Tail, Criteria>))
|
|
17
21
|
: never))
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* keeps entries satisfying `Criteria` in array or tuple `A`.
|
|
25
|
+
*/
|
|
26
|
+
export type KeepMatch<A extends Array<any>, Criteria> = Filter<A, Criteria>
|
package/ts/array/index.ts
CHANGED
|
@@ -3,7 +3,8 @@ export type { Concat } from './Concat'
|
|
|
3
3
|
export type { CreateTuple } from './CreateTuple'
|
|
4
4
|
export type { DropFirst } from './DropFirst'
|
|
5
5
|
export type { DropLast } from './DropLast'
|
|
6
|
-
export type {
|
|
6
|
+
export type { DropMatch } from './DropMatch'
|
|
7
|
+
export type { Filter, KeepMatch } from './Filter'
|
|
7
8
|
export type { FindFirst, First } from './FindFirst'
|
|
8
9
|
export type { FindLast } from './FindLast'
|
|
9
10
|
export type { Head } from './Head'
|
package/ts/math/Add.spec.ts
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
import { Add, Increment, isType } from '..'
|
|
2
|
-
|
|
3
|
-
describe('Add<A, B>', () => {
|
|
4
|
-
test('fractional A gets never', () => {
|
|
5
|
-
isType.equal<true, never, Add<1.1, 1>>()
|
|
6
|
-
})
|
|
7
|
-
|
|
8
|
-
test('negative A gets never', () => {
|
|
9
|
-
isType.equal<true, never, Add<-1, 1>>()
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
test('fractional B gets never', () => {
|
|
13
|
-
isType.equal<true, never, Add<1, 1.2>>()
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
test('negative B gets never', () => {
|
|
17
|
-
isType.equal<true, never, Add<1, -1>>()
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
test('number gets Fail', () => {
|
|
21
|
-
isType.equal<true, never, Add<number, 1>>()
|
|
22
|
-
isType.equal<true, never, Add<1, number>>()
|
|
23
|
-
|
|
24
|
-
isType.equal<true, number, Add<number, 1, number>>()
|
|
25
|
-
isType.equal<true, number, Add<1, number, number>>()
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
describe('single digit', () => {
|
|
29
|
-
test('0 + n = n', () => {
|
|
30
|
-
isType.equal<true, 0, Add<0, 0>>()
|
|
31
|
-
isType.equal<true, 1, Add<0, 1>>()
|
|
32
|
-
isType.equal<true, 2, Add<0, 2>>()
|
|
33
|
-
isType.equal<true, 3, Add<0, 3>>()
|
|
34
|
-
isType.equal<true, 4, Add<0, 4>>()
|
|
35
|
-
isType.equal<true, 5, Add<0, 5>>()
|
|
36
|
-
isType.equal<true, 6, Add<0, 6>>()
|
|
37
|
-
isType.equal<true, 7, Add<0, 7>>()
|
|
38
|
-
isType.equal<true, 8, Add<0, 8>>()
|
|
39
|
-
isType.equal<true, 9, Add<0, 9>>()
|
|
40
|
-
})
|
|
41
|
-
test('9 + n', () => {
|
|
42
|
-
isType.equal<true, 9, Add<9, 0>>()
|
|
43
|
-
isType.equal<true, 10, Add<9, 1>>()
|
|
44
|
-
isType.equal<true, 11, Add<9, 2>>()
|
|
45
|
-
isType.equal<true, 12, Add<9, 3>>()
|
|
46
|
-
isType.equal<true, 13, Add<9, 4>>()
|
|
47
|
-
isType.equal<true, 14, Add<9, 5>>()
|
|
48
|
-
isType.equal<true, 15, Add<9, 6>>()
|
|
49
|
-
isType.equal<true, 16, Add<9, 7>>()
|
|
50
|
-
isType.equal<true, 17, Add<9, 8>>()
|
|
51
|
-
isType.equal<true, 18, Add<9, 9>>()
|
|
52
|
-
})
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
test('1 + 2 digits', () => {
|
|
56
|
-
isType.equal<true, 16, Add<3, 13>>()
|
|
57
|
-
isType.equal<true, 108, Add<9, 99>>()
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
test('2 + 1 digits', () => {
|
|
61
|
-
isType.equal<true, 16, Add<13, 3>>()
|
|
62
|
-
isType.equal<true, 108, Add<99, 9>>()
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
test('2 + 2 digits', () => {
|
|
66
|
-
isType.equal<true, 20, Add<10, 10>>()
|
|
67
|
-
isType.equal<true, 38, Add<19, 19>>()
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
test('n + n digits', () => {
|
|
71
|
-
isType.equal<true, 7777, Add<1234, 6543>>()
|
|
72
|
-
})
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
describe('Increment<A>', () => {
|
|
76
|
-
test('add 1', () => {
|
|
77
|
-
isType.equal<true, 1, Increment<0>>()
|
|
78
|
-
})
|
|
79
|
-
test('work with large number', () => {
|
|
80
|
-
isType.equal<true, 7777, Increment<7776>>()
|
|
81
|
-
})
|
|
82
|
-
})
|
|
1
|
+
import { Add, Increment, isType } from '..'
|
|
2
|
+
|
|
3
|
+
describe('Add<A, B>', () => {
|
|
4
|
+
test('fractional A gets never', () => {
|
|
5
|
+
isType.equal<true, never, Add<1.1, 1>>()
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
test('negative A gets never', () => {
|
|
9
|
+
isType.equal<true, never, Add<-1, 1>>()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('fractional B gets never', () => {
|
|
13
|
+
isType.equal<true, never, Add<1, 1.2>>()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
test('negative B gets never', () => {
|
|
17
|
+
isType.equal<true, never, Add<1, -1>>()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('number gets Fail', () => {
|
|
21
|
+
isType.equal<true, never, Add<number, 1>>()
|
|
22
|
+
isType.equal<true, never, Add<1, number>>()
|
|
23
|
+
|
|
24
|
+
isType.equal<true, number, Add<number, 1, number>>()
|
|
25
|
+
isType.equal<true, number, Add<1, number, number>>()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
describe('single digit', () => {
|
|
29
|
+
test('0 + n = n', () => {
|
|
30
|
+
isType.equal<true, 0, Add<0, 0>>()
|
|
31
|
+
isType.equal<true, 1, Add<0, 1>>()
|
|
32
|
+
isType.equal<true, 2, Add<0, 2>>()
|
|
33
|
+
isType.equal<true, 3, Add<0, 3>>()
|
|
34
|
+
isType.equal<true, 4, Add<0, 4>>()
|
|
35
|
+
isType.equal<true, 5, Add<0, 5>>()
|
|
36
|
+
isType.equal<true, 6, Add<0, 6>>()
|
|
37
|
+
isType.equal<true, 7, Add<0, 7>>()
|
|
38
|
+
isType.equal<true, 8, Add<0, 8>>()
|
|
39
|
+
isType.equal<true, 9, Add<0, 9>>()
|
|
40
|
+
})
|
|
41
|
+
test('9 + n', () => {
|
|
42
|
+
isType.equal<true, 9, Add<9, 0>>()
|
|
43
|
+
isType.equal<true, 10, Add<9, 1>>()
|
|
44
|
+
isType.equal<true, 11, Add<9, 2>>()
|
|
45
|
+
isType.equal<true, 12, Add<9, 3>>()
|
|
46
|
+
isType.equal<true, 13, Add<9, 4>>()
|
|
47
|
+
isType.equal<true, 14, Add<9, 5>>()
|
|
48
|
+
isType.equal<true, 15, Add<9, 6>>()
|
|
49
|
+
isType.equal<true, 16, Add<9, 7>>()
|
|
50
|
+
isType.equal<true, 17, Add<9, 8>>()
|
|
51
|
+
isType.equal<true, 18, Add<9, 9>>()
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('1 + 2 digits', () => {
|
|
56
|
+
isType.equal<true, 16, Add<3, 13>>()
|
|
57
|
+
isType.equal<true, 108, Add<9, 99>>()
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('2 + 1 digits', () => {
|
|
61
|
+
isType.equal<true, 16, Add<13, 3>>()
|
|
62
|
+
isType.equal<true, 108, Add<99, 9>>()
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('2 + 2 digits', () => {
|
|
66
|
+
isType.equal<true, 20, Add<10, 10>>()
|
|
67
|
+
isType.equal<true, 38, Add<19, 19>>()
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
test('n + n digits', () => {
|
|
71
|
+
isType.equal<true, 7777, Add<1234, 6543>>()
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
describe('Increment<A>', () => {
|
|
76
|
+
test('add 1', () => {
|
|
77
|
+
isType.equal<true, 1, Increment<0>>()
|
|
78
|
+
})
|
|
79
|
+
test('work with large number', () => {
|
|
80
|
+
isType.equal<true, 7777, Increment<7776>>()
|
|
81
|
+
})
|
|
82
|
+
})
|
package/ts/math/Digit.spec.ts
CHANGED
|
@@ -1,185 +1,184 @@
|
|
|
1
|
-
import { Equal, isType } from '..'
|
|
2
|
-
import { Digit, DigitArray } from './Digit'
|
|
3
|
-
|
|
4
|
-
describe('DigitArray.ToNumber<DA>', () => {
|
|
5
|
-
test('no digit gets 0', () => {
|
|
6
|
-
type A = DigitArray.ToNumber<[]>
|
|
7
|
-
isType.t<Equal<A, 0>>()
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
test('single digit', () => {
|
|
11
|
-
isType.t<Equal<DigitArray.ToNumber<[0]>, 0>>()
|
|
12
|
-
isType.t<Equal<DigitArray.ToNumber<[1]>, 1>>()
|
|
13
|
-
isType.t<Equal<DigitArray.ToNumber<[2]>, 2>>()
|
|
14
|
-
isType.t<Equal<DigitArray.ToNumber<[3]>, 3>>()
|
|
15
|
-
isType.t<Equal<DigitArray.ToNumber<[4]>, 4>>()
|
|
16
|
-
isType.t<Equal<DigitArray.ToNumber<[5]>, 5>>()
|
|
17
|
-
isType.t<Equal<DigitArray.ToNumber<[6]>, 6>>()
|
|
18
|
-
isType.t<Equal<DigitArray.ToNumber<[7]>, 7>>()
|
|
19
|
-
isType.t<Equal<DigitArray.ToNumber<[8]>, 8>>()
|
|
20
|
-
isType.t<Equal<DigitArray.ToNumber<[9]>, 9>>()
|
|
21
|
-
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
test('two digits', () => {
|
|
25
|
-
isType.t<Equal<DigitArray.ToNumber<[1, 0]>, 10>>()
|
|
26
|
-
isType.t<Equal<DigitArray.ToNumber<[1, 0]>, 10>>()
|
|
27
|
-
isType.t<Equal<DigitArray.ToNumber<[3, 1]>, 31>>()
|
|
28
|
-
isType.t<Equal<DigitArray.ToNumber<[13, 1]>, 131>>()
|
|
29
|
-
isType.t<Equal<DigitArray.ToNumber<[1, 2, 3, 4]>, 1234>>()
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
test('multi digits', () => {
|
|
33
|
-
isType.t<Equal<DigitArray.ToNumber<[1, 2, 3, 4]>, 1234>>()
|
|
34
|
-
isType.t<Equal<DigitArray.ToNumber<[1, 2, 3, 5]>, 1235>>()
|
|
35
|
-
})
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
describe('DigitArray.Shift10<DA>', () => {
|
|
39
|
-
test('zero digit gets the same', () => {
|
|
40
|
-
isType.equal<true, [], DigitArray.Shift10<[]>>()
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
test('single digit gets the same', () => {
|
|
44
|
-
isType.equal<true, [5], DigitArray.Shift10<[5]>>()
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
test('two digits with leading 0 get trimmed', () => {
|
|
48
|
-
isType.equal<true, [5], DigitArray.Shift10<[0, 5]>>()
|
|
49
|
-
})
|
|
50
|
-
test('two digits gets value shifted', () => {
|
|
51
|
-
isType.equal<true, [15], DigitArray.Shift10<[1, 5]>>()
|
|
52
|
-
isType.equal<true, [8, 10], DigitArray.Shift10<[9, 0]>>()
|
|
53
|
-
isType.equal<true, [8, 19], DigitArray.Shift10<[9, 9]>>()
|
|
54
|
-
})
|
|
55
|
-
test('multiple digits', () => {
|
|
56
|
-
isType.equal<true, [11, 12, 14], DigitArray.Shift10<[0, 1, 2, 3, 4]>>()
|
|
57
|
-
})
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
isType.equal<true, false, Digit.GreaterThan<
|
|
64
|
-
isType.equal<true, false, Digit.GreaterThan<
|
|
65
|
-
isType.equal<true, false, Digit.GreaterThan<
|
|
66
|
-
isType.equal<true, false, Digit.GreaterThan<
|
|
67
|
-
isType.equal<true, false, Digit.GreaterThan<
|
|
68
|
-
isType.equal<true, false, Digit.GreaterThan<
|
|
69
|
-
isType.equal<true, false, Digit.GreaterThan<
|
|
70
|
-
isType.equal<true, false, Digit.GreaterThan<
|
|
71
|
-
isType.equal<true, false, Digit.GreaterThan<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
76
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
77
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
78
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
79
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
80
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
81
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
82
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
86
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
87
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
88
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
89
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
90
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
91
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
95
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
96
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
97
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
98
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
99
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
103
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
104
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
105
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
106
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
110
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
111
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
112
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
116
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
117
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
121
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
isType.equal<true, true, Digit.GreaterThan<
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
isType.equal<true, false, Digit.GreaterThan<0,
|
|
132
|
-
isType.equal<true, false, Digit.GreaterThan<0,
|
|
133
|
-
isType.equal<true, false, Digit.GreaterThan<0,
|
|
134
|
-
isType.equal<true, false, Digit.GreaterThan<0,
|
|
135
|
-
isType.equal<true, false, Digit.GreaterThan<0,
|
|
136
|
-
isType.equal<true, false, Digit.GreaterThan<0,
|
|
137
|
-
isType.equal<true, false, Digit.GreaterThan<0,
|
|
138
|
-
isType.equal<true, false, Digit.GreaterThan<0,
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
isType.equal<true, false, Digit.GreaterThan<1,
|
|
142
|
-
isType.equal<true, false, Digit.GreaterThan<1,
|
|
143
|
-
isType.equal<true, false, Digit.GreaterThan<1,
|
|
144
|
-
isType.equal<true, false, Digit.GreaterThan<1,
|
|
145
|
-
isType.equal<true, false, Digit.GreaterThan<1,
|
|
146
|
-
isType.equal<true, false, Digit.GreaterThan<1,
|
|
147
|
-
isType.equal<true, false, Digit.GreaterThan<1,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
isType.equal<true, false, Digit.GreaterThan<2,
|
|
151
|
-
isType.equal<true, false, Digit.GreaterThan<2,
|
|
152
|
-
isType.equal<true, false, Digit.GreaterThan<2,
|
|
153
|
-
isType.equal<true, false, Digit.GreaterThan<2,
|
|
154
|
-
isType.equal<true, false, Digit.GreaterThan<2,
|
|
155
|
-
isType.equal<true, false, Digit.GreaterThan<2,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
isType.equal<true, false, Digit.GreaterThan<3,
|
|
159
|
-
isType.equal<true, false, Digit.GreaterThan<3,
|
|
160
|
-
isType.equal<true, false, Digit.GreaterThan<3,
|
|
161
|
-
isType.equal<true, false, Digit.GreaterThan<3,
|
|
162
|
-
isType.equal<true, false, Digit.GreaterThan<3,
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
isType.equal<true, false, Digit.GreaterThan<4,
|
|
166
|
-
isType.equal<true, false, Digit.GreaterThan<4,
|
|
167
|
-
isType.equal<true, false, Digit.GreaterThan<4,
|
|
168
|
-
isType.equal<true, false, Digit.GreaterThan<4,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
isType.equal<true, false, Digit.GreaterThan<5,
|
|
172
|
-
isType.equal<true, false, Digit.GreaterThan<5,
|
|
173
|
-
isType.equal<true, false, Digit.GreaterThan<5,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
isType.equal<true, false, Digit.GreaterThan<6,
|
|
177
|
-
isType.equal<true, false, Digit.GreaterThan<6,
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
isType.equal<true, false, Digit.GreaterThan<7,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
})
|
|
1
|
+
import { Equal, isType } from '..'
|
|
2
|
+
import { Digit, DigitArray } from './Digit'
|
|
3
|
+
|
|
4
|
+
describe('DigitArray.ToNumber<DA>', () => {
|
|
5
|
+
test('no digit gets 0', () => {
|
|
6
|
+
type A = DigitArray.ToNumber<[]>
|
|
7
|
+
isType.t<Equal<A, 0>>()
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test('single digit', () => {
|
|
11
|
+
isType.t<Equal<DigitArray.ToNumber<[0]>, 0>>()
|
|
12
|
+
isType.t<Equal<DigitArray.ToNumber<[1]>, 1>>()
|
|
13
|
+
isType.t<Equal<DigitArray.ToNumber<[2]>, 2>>()
|
|
14
|
+
isType.t<Equal<DigitArray.ToNumber<[3]>, 3>>()
|
|
15
|
+
isType.t<Equal<DigitArray.ToNumber<[4]>, 4>>()
|
|
16
|
+
isType.t<Equal<DigitArray.ToNumber<[5]>, 5>>()
|
|
17
|
+
isType.t<Equal<DigitArray.ToNumber<[6]>, 6>>()
|
|
18
|
+
isType.t<Equal<DigitArray.ToNumber<[7]>, 7>>()
|
|
19
|
+
isType.t<Equal<DigitArray.ToNumber<[8]>, 8>>()
|
|
20
|
+
isType.t<Equal<DigitArray.ToNumber<[9]>, 9>>()
|
|
21
|
+
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('two digits', () => {
|
|
25
|
+
isType.t<Equal<DigitArray.ToNumber<[1, 0]>, 10>>()
|
|
26
|
+
isType.t<Equal<DigitArray.ToNumber<[1, 0]>, 10>>()
|
|
27
|
+
isType.t<Equal<DigitArray.ToNumber<[3, 1]>, 31>>()
|
|
28
|
+
isType.t<Equal<DigitArray.ToNumber<[13, 1]>, 131>>()
|
|
29
|
+
isType.t<Equal<DigitArray.ToNumber<[1, 2, 3, 4]>, 1234>>()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('multi digits', () => {
|
|
33
|
+
isType.t<Equal<DigitArray.ToNumber<[1, 2, 3, 4]>, 1234>>()
|
|
34
|
+
isType.t<Equal<DigitArray.ToNumber<[1, 2, 3, 5]>, 1235>>()
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe('DigitArray.Shift10<DA>', () => {
|
|
39
|
+
test('zero digit gets the same', () => {
|
|
40
|
+
isType.equal<true, [], DigitArray.Shift10<[]>>()
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('single digit gets the same', () => {
|
|
44
|
+
isType.equal<true, [5], DigitArray.Shift10<[5]>>()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('two digits with leading 0 get trimmed', () => {
|
|
48
|
+
isType.equal<true, [5], DigitArray.Shift10<[0, 5]>>()
|
|
49
|
+
})
|
|
50
|
+
test('two digits gets value shifted', () => {
|
|
51
|
+
isType.equal<true, [15], DigitArray.Shift10<[1, 5]>>()
|
|
52
|
+
isType.equal<true, [8, 10], DigitArray.Shift10<[9, 0]>>()
|
|
53
|
+
isType.equal<true, [8, 19], DigitArray.Shift10<[9, 9]>>()
|
|
54
|
+
})
|
|
55
|
+
test('multiple digits', () => {
|
|
56
|
+
isType.equal<true, [11, 12, 14], DigitArray.Shift10<[0, 1, 2, 3, 4]>>()
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
describe('Digit.GreaterThan<A, B>', () => {
|
|
61
|
+
test('n > n is false', () => {
|
|
62
|
+
isType.equal<true, false, Digit.GreaterThan<0, 0>>()
|
|
63
|
+
isType.equal<true, false, Digit.GreaterThan<1, 1>>()
|
|
64
|
+
isType.equal<true, false, Digit.GreaterThan<2, 2>>()
|
|
65
|
+
isType.equal<true, false, Digit.GreaterThan<3, 3>>()
|
|
66
|
+
isType.equal<true, false, Digit.GreaterThan<4, 4>>()
|
|
67
|
+
isType.equal<true, false, Digit.GreaterThan<5, 5>>()
|
|
68
|
+
isType.equal<true, false, Digit.GreaterThan<6, 6>>()
|
|
69
|
+
isType.equal<true, false, Digit.GreaterThan<7, 7>>()
|
|
70
|
+
isType.equal<true, false, Digit.GreaterThan<8, 8>>()
|
|
71
|
+
isType.equal<true, false, Digit.GreaterThan<9, 9>>()
|
|
72
|
+
})
|
|
73
|
+
test('N > m is true', () => {
|
|
74
|
+
isType.equal<true, true, Digit.GreaterThan<1, 0>>()
|
|
75
|
+
isType.equal<true, true, Digit.GreaterThan<2, 0>>()
|
|
76
|
+
isType.equal<true, true, Digit.GreaterThan<3, 0>>()
|
|
77
|
+
isType.equal<true, true, Digit.GreaterThan<4, 0>>()
|
|
78
|
+
isType.equal<true, true, Digit.GreaterThan<5, 0>>()
|
|
79
|
+
isType.equal<true, true, Digit.GreaterThan<6, 0>>()
|
|
80
|
+
isType.equal<true, true, Digit.GreaterThan<7, 0>>()
|
|
81
|
+
isType.equal<true, true, Digit.GreaterThan<8, 0>>()
|
|
82
|
+
isType.equal<true, true, Digit.GreaterThan<9, 0>>()
|
|
83
|
+
|
|
84
|
+
isType.equal<true, true, Digit.GreaterThan<2, 1>>()
|
|
85
|
+
isType.equal<true, true, Digit.GreaterThan<3, 1>>()
|
|
86
|
+
isType.equal<true, true, Digit.GreaterThan<4, 1>>()
|
|
87
|
+
isType.equal<true, true, Digit.GreaterThan<5, 1>>()
|
|
88
|
+
isType.equal<true, true, Digit.GreaterThan<6, 1>>()
|
|
89
|
+
isType.equal<true, true, Digit.GreaterThan<7, 1>>()
|
|
90
|
+
isType.equal<true, true, Digit.GreaterThan<8, 1>>()
|
|
91
|
+
isType.equal<true, true, Digit.GreaterThan<9, 1>>()
|
|
92
|
+
|
|
93
|
+
isType.equal<true, true, Digit.GreaterThan<3, 2>>()
|
|
94
|
+
isType.equal<true, true, Digit.GreaterThan<4, 2>>()
|
|
95
|
+
isType.equal<true, true, Digit.GreaterThan<5, 2>>()
|
|
96
|
+
isType.equal<true, true, Digit.GreaterThan<6, 2>>()
|
|
97
|
+
isType.equal<true, true, Digit.GreaterThan<7, 2>>()
|
|
98
|
+
isType.equal<true, true, Digit.GreaterThan<8, 2>>()
|
|
99
|
+
isType.equal<true, true, Digit.GreaterThan<9, 2>>()
|
|
100
|
+
|
|
101
|
+
isType.equal<true, true, Digit.GreaterThan<4, 3>>()
|
|
102
|
+
isType.equal<true, true, Digit.GreaterThan<5, 3>>()
|
|
103
|
+
isType.equal<true, true, Digit.GreaterThan<6, 3>>()
|
|
104
|
+
isType.equal<true, true, Digit.GreaterThan<7, 3>>()
|
|
105
|
+
isType.equal<true, true, Digit.GreaterThan<8, 3>>()
|
|
106
|
+
isType.equal<true, true, Digit.GreaterThan<9, 3>>()
|
|
107
|
+
|
|
108
|
+
isType.equal<true, true, Digit.GreaterThan<5, 4>>()
|
|
109
|
+
isType.equal<true, true, Digit.GreaterThan<6, 4>>()
|
|
110
|
+
isType.equal<true, true, Digit.GreaterThan<7, 4>>()
|
|
111
|
+
isType.equal<true, true, Digit.GreaterThan<8, 4>>()
|
|
112
|
+
isType.equal<true, true, Digit.GreaterThan<9, 4>>()
|
|
113
|
+
|
|
114
|
+
isType.equal<true, true, Digit.GreaterThan<6, 5>>()
|
|
115
|
+
isType.equal<true, true, Digit.GreaterThan<7, 5>>()
|
|
116
|
+
isType.equal<true, true, Digit.GreaterThan<8, 5>>()
|
|
117
|
+
isType.equal<true, true, Digit.GreaterThan<9, 5>>()
|
|
118
|
+
|
|
119
|
+
isType.equal<true, true, Digit.GreaterThan<7, 6>>()
|
|
120
|
+
isType.equal<true, true, Digit.GreaterThan<8, 6>>()
|
|
121
|
+
isType.equal<true, true, Digit.GreaterThan<9, 6>>()
|
|
122
|
+
|
|
123
|
+
isType.equal<true, true, Digit.GreaterThan<8, 7>>()
|
|
124
|
+
isType.equal<true, true, Digit.GreaterThan<9, 7>>()
|
|
125
|
+
|
|
126
|
+
isType.equal<true, true, Digit.GreaterThan<9, 8>>()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
test('n > M is false', () => {
|
|
130
|
+
isType.equal<true, false, Digit.GreaterThan<0, 1>>()
|
|
131
|
+
isType.equal<true, false, Digit.GreaterThan<0, 2>>()
|
|
132
|
+
isType.equal<true, false, Digit.GreaterThan<0, 3>>()
|
|
133
|
+
isType.equal<true, false, Digit.GreaterThan<0, 4>>()
|
|
134
|
+
isType.equal<true, false, Digit.GreaterThan<0, 5>>()
|
|
135
|
+
isType.equal<true, false, Digit.GreaterThan<0, 6>>()
|
|
136
|
+
isType.equal<true, false, Digit.GreaterThan<0, 7>>()
|
|
137
|
+
isType.equal<true, false, Digit.GreaterThan<0, 8>>()
|
|
138
|
+
isType.equal<true, false, Digit.GreaterThan<0, 9>>()
|
|
139
|
+
|
|
140
|
+
isType.equal<true, false, Digit.GreaterThan<1, 2>>()
|
|
141
|
+
isType.equal<true, false, Digit.GreaterThan<1, 3>>()
|
|
142
|
+
isType.equal<true, false, Digit.GreaterThan<1, 4>>()
|
|
143
|
+
isType.equal<true, false, Digit.GreaterThan<1, 5>>()
|
|
144
|
+
isType.equal<true, false, Digit.GreaterThan<1, 6>>()
|
|
145
|
+
isType.equal<true, false, Digit.GreaterThan<1, 7>>()
|
|
146
|
+
isType.equal<true, false, Digit.GreaterThan<1, 8>>()
|
|
147
|
+
isType.equal<true, false, Digit.GreaterThan<1, 9>>()
|
|
148
|
+
|
|
149
|
+
isType.equal<true, false, Digit.GreaterThan<2, 3>>()
|
|
150
|
+
isType.equal<true, false, Digit.GreaterThan<2, 4>>()
|
|
151
|
+
isType.equal<true, false, Digit.GreaterThan<2, 5>>()
|
|
152
|
+
isType.equal<true, false, Digit.GreaterThan<2, 6>>()
|
|
153
|
+
isType.equal<true, false, Digit.GreaterThan<2, 7>>()
|
|
154
|
+
isType.equal<true, false, Digit.GreaterThan<2, 8>>()
|
|
155
|
+
isType.equal<true, false, Digit.GreaterThan<2, 9>>()
|
|
156
|
+
|
|
157
|
+
isType.equal<true, false, Digit.GreaterThan<3, 4>>()
|
|
158
|
+
isType.equal<true, false, Digit.GreaterThan<3, 5>>()
|
|
159
|
+
isType.equal<true, false, Digit.GreaterThan<3, 6>>()
|
|
160
|
+
isType.equal<true, false, Digit.GreaterThan<3, 7>>()
|
|
161
|
+
isType.equal<true, false, Digit.GreaterThan<3, 8>>()
|
|
162
|
+
isType.equal<true, false, Digit.GreaterThan<3, 9>>()
|
|
163
|
+
|
|
164
|
+
isType.equal<true, false, Digit.GreaterThan<4, 5>>()
|
|
165
|
+
isType.equal<true, false, Digit.GreaterThan<4, 6>>()
|
|
166
|
+
isType.equal<true, false, Digit.GreaterThan<4, 7>>()
|
|
167
|
+
isType.equal<true, false, Digit.GreaterThan<4, 8>>()
|
|
168
|
+
isType.equal<true, false, Digit.GreaterThan<4, 9>>()
|
|
169
|
+
|
|
170
|
+
isType.equal<true, false, Digit.GreaterThan<5, 6>>()
|
|
171
|
+
isType.equal<true, false, Digit.GreaterThan<5, 7>>()
|
|
172
|
+
isType.equal<true, false, Digit.GreaterThan<5, 8>>()
|
|
173
|
+
isType.equal<true, false, Digit.GreaterThan<5, 9>>()
|
|
174
|
+
|
|
175
|
+
isType.equal<true, false, Digit.GreaterThan<6, 7>>()
|
|
176
|
+
isType.equal<true, false, Digit.GreaterThan<6, 8>>()
|
|
177
|
+
isType.equal<true, false, Digit.GreaterThan<6, 9>>()
|
|
178
|
+
|
|
179
|
+
isType.equal<true, false, Digit.GreaterThan<7, 8>>()
|
|
180
|
+
isType.equal<true, false, Digit.GreaterThan<7, 9>>()
|
|
181
|
+
|
|
182
|
+
isType.equal<true, false, Digit.GreaterThan<8, 9>>()
|
|
183
|
+
})
|
|
184
|
+
})
|
package/ts/math/Digit.ts
CHANGED
|
@@ -4,29 +4,29 @@ import { IsPositive } from './IsPositive'
|
|
|
4
4
|
import { IsWhole } from './IsWhole'
|
|
5
5
|
|
|
6
6
|
export namespace Digit {
|
|
7
|
-
export type ToTuple = {
|
|
7
|
+
export type ToTuple<T = 1> = {
|
|
8
8
|
[k in number]: any[]
|
|
9
9
|
} & {
|
|
10
10
|
0: [],
|
|
11
|
-
1: [
|
|
12
|
-
2: [
|
|
13
|
-
3: [
|
|
14
|
-
4: [
|
|
15
|
-
5: [
|
|
16
|
-
6: [
|
|
17
|
-
7: [
|
|
18
|
-
8: [
|
|
19
|
-
9: [
|
|
20
|
-
10: [
|
|
21
|
-
11: [
|
|
22
|
-
12: [
|
|
23
|
-
13: [
|
|
24
|
-
14: [
|
|
25
|
-
15: [
|
|
26
|
-
16: [
|
|
27
|
-
17: [
|
|
28
|
-
18: [
|
|
29
|
-
19: [
|
|
11
|
+
1: [T],
|
|
12
|
+
2: [T, T],
|
|
13
|
+
3: [T, T, T],
|
|
14
|
+
4: [T, T, T, T],
|
|
15
|
+
5: [T, T, T, T, T],
|
|
16
|
+
6: [T, T, T, T, T, T],
|
|
17
|
+
7: [T, T, T, T, T, T, T],
|
|
18
|
+
8: [T, T, T, T, T, T, T, T],
|
|
19
|
+
9: [T, T, T, T, T, T, T, T, T],
|
|
20
|
+
10: [T, T, T, T, T, T, T, T, T, T],
|
|
21
|
+
11: [T, T, T, T, T, T, T, T, T, T, T],
|
|
22
|
+
12: [T, T, T, T, T, T, T, T, T, T, T, T],
|
|
23
|
+
13: [T, T, T, T, T, T, T, T, T, T, T, T, T],
|
|
24
|
+
14: [T, T, T, T, T, T, T, T, T, T, T, T, T, T],
|
|
25
|
+
15: [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T],
|
|
26
|
+
16: [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T],
|
|
27
|
+
17: [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T],
|
|
28
|
+
18: [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T],
|
|
29
|
+
19: [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T],
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
@@ -51,14 +51,14 @@ export namespace Digit {
|
|
|
51
51
|
export namespace DigitArray {
|
|
52
52
|
export type ToNumber<C extends number[]> = ToTuple<[], C>['length']
|
|
53
53
|
|
|
54
|
-
export type ToTuple<R extends any[], S extends number[]> =
|
|
54
|
+
export type ToTuple<R extends any[], S extends number[], X = any> =
|
|
55
55
|
S['length'] extends 0
|
|
56
56
|
? R
|
|
57
57
|
: (S['length'] extends 1
|
|
58
|
-
? [...R, ...Digit.ToTuple[S[0]]]
|
|
58
|
+
? [...R, ...Digit.ToTuple<X>[S[0]]]
|
|
59
59
|
: (S extends [any, ...infer T]
|
|
60
60
|
? (T extends any[]
|
|
61
|
-
? ToTuple<Multi10<[...R, ...Digit.ToTuple[S[0]]]>, T>
|
|
61
|
+
? ToTuple<Multi10<[...R, ...Digit.ToTuple<X>[S[0]]]>, T>
|
|
62
62
|
: never)
|
|
63
63
|
: never))
|
|
64
64
|
|