type-plus 4.6.2 → 4.6.3
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 +4 -0
- package/cjs/array/drop.d.ts +12 -0
- package/cjs/array/drop.js +8 -0
- package/cjs/array/drop.js.map +1 -0
- package/cjs/array/index.d.ts +1 -3
- package/cjs/array/index.js +1 -0
- package/cjs/array/index.js.map +1 -1
- package/cjs/object/split.d.ts +3 -2
- package/cjs/object/split.js +3 -3
- package/cjs/object/split.js.map +1 -1
- package/cjs/utils/NonNull.d.ts +1 -0
- package/cjs/{array/DropLast.js → utils/NonNull.js} +1 -1
- package/cjs/utils/NonNull.js.map +1 -0
- package/cjs/utils/NonUndefined.d.ts +1 -0
- package/cjs/{array/DropFirst.js → utils/NonUndefined.js} +1 -1
- package/cjs/utils/NonUndefined.js.map +1 -0
- package/cjs/utils/index.d.ts +2 -0
- package/esm/array/drop.js +4 -0
- package/esm/array/drop.js.map +1 -0
- package/esm/array/index.js +1 -0
- package/esm/array/index.js.map +1 -1
- package/esm/object/split.js +1 -1
- package/esm/object/split.js.map +1 -1
- package/esm/utils/NonNull.js +2 -0
- package/esm/utils/NonNull.js.map +1 -0
- package/esm/utils/NonUndefined.js +2 -0
- package/esm/utils/NonUndefined.js.map +1 -0
- package/package.json +1 -1
- package/ts/array/DropMatch.spec.ts +124 -3
- package/ts/array/drop.ts +72 -0
- package/ts/array/index.ts +2 -3
- package/ts/array/literalArray.spec.ts +2 -5
- package/ts/object/split.spec.ts +48 -1
- package/ts/object/split.ts +10 -3
- package/ts/utils/NonNull.ts +1 -0
- package/ts/utils/NonUndefined.ts +1 -0
- package/ts/utils/index.ts +2 -0
- package/cjs/array/DropFirst.d.ts +0 -1
- package/cjs/array/DropFirst.js.map +0 -1
- package/cjs/array/DropLast.d.ts +0 -1
- package/cjs/array/DropLast.js.map +0 -1
- package/cjs/array/DropMatch.d.ts +0 -5
- package/cjs/array/DropMatch.js +0 -3
- package/cjs/array/DropMatch.js.map +0 -1
- package/esm/array/DropFirst.js +0 -2
- package/esm/array/DropFirst.js.map +0 -1
- package/esm/array/DropLast.js +0 -2
- package/esm/array/DropLast.js.map +0 -1
- package/esm/array/DropMatch.js +0 -2
- package/esm/array/DropMatch.js.map +0 -1
- package/ts/array/DropFirst.ts +0 -9
- package/ts/array/DropLast.ts +0 -9
- package/ts/array/DropMatch.ts +0 -53
package/README.md
CHANGED
|
@@ -283,9 +283,11 @@ type No = IsAny<1, 'yes', 'no'> // 'no'
|
|
|
283
283
|
- `CommonPropKeys<A>`: gets common keys inside the records in the array `A` (deprecate `CommonKeys`).
|
|
284
284
|
- `Concat<A, B>`: `[...A, ...B]`.
|
|
285
285
|
- `CreateTuple<L, T>`: Creates `Tuple<T>` with `L` number of elements.
|
|
286
|
+
- `drop(array, value)`: drop a particular value from an array.
|
|
286
287
|
- `DropFirst<A>`: drops the first value type of `A`.
|
|
287
288
|
- `DropLast<A>`: drops the last value type of `A`.
|
|
288
289
|
- `DropMatch<A, Criteria>`: drops entries matching `Criteria` in array or tuple `A`.
|
|
290
|
+
- `DropUndefined<A>`: drop undefined entries from array of tuple `A`.
|
|
289
291
|
- `Filter<A, Criteria>`: filter the array or tuple `A`, keeping entries satisfying `Criteria`. **deprecated. Renaming to `KeepMatch`**
|
|
290
292
|
- `FindFirst<A, Criteria>`: gets the first type satisfying `Criteria`.
|
|
291
293
|
- `FindLast<A, Criteria>`: gets the last type satisfying `Criteria`.
|
|
@@ -360,6 +362,8 @@ JSONTypes.get<string>(someJson, 'a', 'b', 1, 'c') // miku
|
|
|
360
362
|
- `KeyofOptional<T>`: `keyof` that works with `Record<any, any> | undefined`.
|
|
361
363
|
- `KnownKeys<T>`: extract known (defined) keys from type `T`.
|
|
362
364
|
- `LeftJoin<A, B>`: left join `A` with `B`
|
|
365
|
+
- `NonNull<T>`: remove `null`
|
|
366
|
+
- `NonUndefined<T>`: remove `undefined`
|
|
363
367
|
- `Omit<T, K>`: From `T`, pick a set of properties whose keys are not in the union `K`. This is the opposite of `Pick<T, K>`.
|
|
364
368
|
- `OptionalKeys<T>`: gets keys of optional properties in `T`.
|
|
365
369
|
- `PartialExcept<T, U>`: Deprecated. Same as `PartialOmit<T, U>`.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Equal } from '../predicates';
|
|
2
|
+
import { NonNull, NonUndefined } from '../utils';
|
|
3
|
+
export declare type DropFirst<A extends any[]> = number extends A['length'] ? A : (A['length'] extends 0 ? never[] : (A['length'] extends 1 ? never[] : (A extends [any, ...infer Tail] ? Tail : never)));
|
|
4
|
+
export declare type DropLast<A extends any[]> = number extends A['length'] ? A : (A['length'] extends 0 ? never[] : (A['length'] extends 1 ? never[] : (A extends [...infer Heads, any] ? Heads : never)));
|
|
5
|
+
declare type ExcludeUnionOfEmptyTuple<A> = Equal<A, []> extends true ? A : Exclude<A, []>;
|
|
6
|
+
export declare type DropMatch<A extends Readonly<Array<any>>, Criteria> = number extends A['length'] ? (A[0] extends Criteria ? never[] : (undefined extends Criteria ? (null extends Criteria ? Array<NonNullable<A[0]>> : Array<NonUndefined<A[0]>>) : (null extends Criteria ? Array<NonNull<A[0]>> : (Criteria extends A[0] ? Array<Exclude<A[0], Criteria>> : (A[0] extends Criteria ? A : Array<Exclude<A[0], Criteria>>))))) : DropMatchTuple<A, Criteria>;
|
|
7
|
+
declare type DropMatchTuple<A extends Readonly<Array<any>>, Criteria> = A['length'] extends 0 ? A : (A extends readonly [infer Head, ...infer Tail] ? (Tail['length'] extends 0 ? (undefined extends Criteria ? ExcludeUnionOfEmptyTuple<Head extends Criteria ? [] : [Head]> : ExcludeUnionOfEmptyTuple<Head extends Criteria ? [] : [Head]>) : (Exclude<Head, Criteria> extends never ? DropMatch<Tail, Criteria> : [Exclude<Head, Criteria>, ...DropMatch<Tail, Criteria>])) : never[]);
|
|
8
|
+
export declare type DropNull<A extends Array<any>> = DropMatch<A, null>;
|
|
9
|
+
export declare type DropNullable<A extends Array<any>> = DropMatch<A, null | undefined>;
|
|
10
|
+
export declare type DropUndefined<A extends Array<any>> = DropMatch<A, undefined>;
|
|
11
|
+
export declare function drop<A extends Readonly<Array<any>>, C>(array: A, value: C): DropMatch<A, C>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drop.js","sourceRoot":"","sources":["../../ts/array/drop.ts"],"names":[],"mappings":";;;AAqEA,SAAgB,IAAI,CAAoC,KAAQ,EAAE,KAAQ;IACxE,OAAO,KAAK,CAAC,MAAM,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,KAAK,KAAK,EAAX,CAAW,CAAQ,CAAA;AAC9C,CAAC;AAFD,oBAEC"}
|
package/cjs/array/index.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export type { CommonKeys, CommonPropKeys } from './CommonPropKeys';
|
|
2
2
|
export type { Concat } from './Concat';
|
|
3
3
|
export type { CreateTuple } from './CreateTuple';
|
|
4
|
-
export
|
|
5
|
-
export type { DropLast } from './DropLast';
|
|
6
|
-
export type { DropMatch } from './DropMatch';
|
|
4
|
+
export * from './drop';
|
|
7
5
|
export type { Filter, KeepMatch } from './Filter';
|
|
8
6
|
export type { FindFirst, First } from './FindFirst';
|
|
9
7
|
export type { FindLast } from './FindLast';
|
package/cjs/array/index.js
CHANGED
|
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./drop"), exports);
|
|
17
18
|
__exportStar(require("./literalArray"), exports);
|
|
18
19
|
__exportStar(require("./reduceWhile"), exports);
|
|
19
20
|
//# sourceMappingURL=index.js.map
|
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":";;;;;;;;;;;;;;;;AAGA,yCAAsB;AAQtB,iDAA8B;AAE9B,gDAA6B"}
|
package/cjs/object/split.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { AnyRecord
|
|
1
|
+
import { AnyRecord } from './AnyRecord';
|
|
2
|
+
import { Omit } from './omit';
|
|
2
3
|
declare type Splitter<T extends AnyRecord> = Partial<{
|
|
3
4
|
[k in keyof T]: T[k] | undefined;
|
|
4
5
|
}>;
|
|
5
6
|
export declare type Split<T extends AnyRecord, S extends AnyRecord> = {
|
|
6
|
-
[k in keyof S]: NonNullable<T[k]> | S[k];
|
|
7
|
+
[k in keyof S]: S[k] extends undefined ? T[k] : NonNullable<T[k]> | S[k];
|
|
7
8
|
};
|
|
8
9
|
export declare function split<T extends AnyRecord, S1 extends Splitter<T>>(target: T, split1: S1): [
|
|
9
10
|
Split<T, S1>,
|
package/cjs/object/split.js
CHANGED
|
@@ -10,15 +10,15 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.split = void 0;
|
|
13
|
-
var
|
|
13
|
+
var reduceKey_1 = require("./reduceKey");
|
|
14
14
|
function split(target) {
|
|
15
15
|
var splitters = [];
|
|
16
16
|
for (var _i = 1; _i < arguments.length; _i++) {
|
|
17
17
|
splitters[_i - 1] = arguments[_i];
|
|
18
18
|
}
|
|
19
19
|
var keyMap = {};
|
|
20
|
-
var s = splitters.map(function (s) { return (0,
|
|
21
|
-
var r = (0,
|
|
20
|
+
var s = splitters.map(function (s) { return (0, reduceKey_1.reduceByKey)(s, function (p, k) { var _a; return (keyMap[k] = true, p[k] = (_a = target[k]) !== null && _a !== void 0 ? _a : s[k], p); }, {}); });
|
|
21
|
+
var r = (0, reduceKey_1.reduceByKey)(target, function (p, k) { return keyMap[k] ? p : (p[k] = target[k], p); }, {});
|
|
22
22
|
return __spreadArray(__spreadArray([], s, true), [r], false);
|
|
23
23
|
}
|
|
24
24
|
exports.split = split;
|
package/cjs/object/split.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split.js","sourceRoot":"","sources":["../../ts/object/split.ts"],"names":[],"mappings":";;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"split.js","sourceRoot":"","sources":["../../ts/object/split.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,yCAAyC;AA+LzC,SAAgB,KAAK,CAAC,MAAiB;IAAE,mBAAyB;SAAzB,UAAyB,EAAzB,qBAAyB,EAAzB,IAAyB;QAAzB,kCAAyB;;IAChE,IAAM,MAAM,GAAc,EAAE,CAAA;IAC5B,IAAM,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,UAAA,CAAC,IAAI,OAAA,IAAA,uBAAW,EACtC,CAAC,EACD,UAAC,CAAC,EAAE,CAAC,YAAK,OAAA,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,MAAA,MAAM,CAAC,CAAC,CAAC,mCAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA,EAAA,EAC1D,EAAe,CAAC,EAHW,CAGX,CAAC,CAAA;IACnB,IAAM,CAAC,GAAG,IAAA,uBAAW,EAAC,MAAM,EAAE,UAAC,CAAC,EAAE,CAAC,IAAK,OAAA,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAArC,CAAqC,EAAE,EAAe,CAAC,CAAA;IAC/F,uCAAW,CAAC,UAAE,CAAC,UAAC;AAClB,CAAC;AARD,sBAQC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare type NonNull<T> = T extends null ? never : T;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NonNull.js","sourceRoot":"","sources":["../../ts/utils/NonNull.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare type NonUndefined<T> = T extends undefined ? never : T;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NonUndefined.js","sourceRoot":"","sources":["../../ts/utils/NonUndefined.ts"],"names":[],"mappings":""}
|
package/cjs/utils/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drop.js","sourceRoot":"","sources":["../../ts/array/drop.ts"],"names":[],"mappings":"AAqEA,MAAM,UAAU,IAAI,CAAoC,KAAQ,EAAE,KAAQ;IACxE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,KAAK,CAAQ,CAAA;AAC9C,CAAC"}
|
package/esm/array/index.js
CHANGED
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":"AAGA,cAAc,QAAQ,CAAA;AAQtB,cAAc,gBAAgB,CAAA;AAE9B,cAAc,eAAe,CAAA"}
|
package/esm/object/split.js
CHANGED
package/esm/object/split.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split.js","sourceRoot":"","sources":["../../ts/object/split.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"split.js","sourceRoot":"","sources":["../../ts/object/split.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AA+LzC,MAAM,UAAU,KAAK,CAAC,MAAiB,EAAE,GAAG,SAAsB;IAChE,MAAM,MAAM,GAAc,EAAE,CAAA;IAC5B,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CACtC,CAAC,EACD,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,IAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAC1D,EAAe,CAAC,CAAC,CAAA;IACnB,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAe,CAAC,CAAA;IAC/F,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NonNull.js","sourceRoot":"","sources":["../../ts/utils/NonNull.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NonUndefined.js","sourceRoot":"","sources":["../../ts/utils/NonUndefined.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DropMatch, isType } from '..'
|
|
1
|
+
import { drop, DropMatch, DropNull, DropNullable, DropUndefined, isType } from '..'
|
|
2
2
|
|
|
3
3
|
describe('DropMatch<A, C>', () => {
|
|
4
4
|
describe('A is array', () => {
|
|
@@ -34,12 +34,41 @@ describe('DropMatch<A, C>', () => {
|
|
|
34
34
|
|
|
35
35
|
isType.equal<true, Array<string | undefined>, Actual>()
|
|
36
36
|
})
|
|
37
|
+
|
|
38
|
+
test('drop all narrow types', () => {
|
|
39
|
+
type A = DropMatch<Array<1 | 2 | 3>, number>
|
|
40
|
+
isType.equal<true, never[], A>()
|
|
41
|
+
|
|
42
|
+
type B = DropMatch<Array<1 | 2 | 3 | string>, number>
|
|
43
|
+
isType.equal<true, string[], B>()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
test('will not drop widen type', () => {
|
|
48
|
+
type A = DropMatch<Array<number>, 1>
|
|
49
|
+
isType.equal<true, number[], A>()
|
|
50
|
+
|
|
51
|
+
type B = DropMatch<Array<string | 'foo'>, 'foo'>
|
|
52
|
+
isType.equal<true, string[], B>()
|
|
53
|
+
|
|
54
|
+
// C is currently `string[] | string[]` (TypeScript 4.6.2)
|
|
55
|
+
// It does not collapse to `string[]`
|
|
56
|
+
// type C = DropMatch<Array<string | 'foo'>, 'foo' | 'boo'>
|
|
57
|
+
// Here `string[] | string[]` literal collapses to `string[]`
|
|
58
|
+
// commenting this out as it will likely be improved in future versions of TypeScript
|
|
59
|
+
// isType.equal<true, string[] | string[], C>()
|
|
60
|
+
})
|
|
37
61
|
})
|
|
38
62
|
|
|
39
63
|
describe('A is Tuple', () => {
|
|
40
64
|
test('empty tuple', () => {
|
|
41
65
|
type A = DropMatch<[], undefined>
|
|
42
66
|
isType.equal<true, [], A>()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('drop undefined from tuple', () => {
|
|
70
|
+
type A = DropMatch<[undefined], undefined>
|
|
71
|
+
isType.equal<true, [], A>()
|
|
43
72
|
|
|
44
73
|
type B = DropMatch<[1, undefined], undefined>
|
|
45
74
|
isType.equal<true, [1], B>()
|
|
@@ -51,8 +80,8 @@ describe('DropMatch<A, C>', () => {
|
|
|
51
80
|
isType.equal<true, [1, string, 3], D>()
|
|
52
81
|
})
|
|
53
82
|
|
|
54
|
-
test('drop undefined from tuple', () => {
|
|
55
|
-
type A = DropMatch<[undefined], undefined>
|
|
83
|
+
test('drop undefined from readonly tuple', () => {
|
|
84
|
+
type A = DropMatch<readonly [undefined], undefined>
|
|
56
85
|
isType.equal<true, [], A>()
|
|
57
86
|
|
|
58
87
|
type B = DropMatch<[1, undefined], undefined>
|
|
@@ -65,6 +94,24 @@ describe('DropMatch<A, C>', () => {
|
|
|
65
94
|
isType.equal<true, [1, string, 3], D>()
|
|
66
95
|
})
|
|
67
96
|
|
|
97
|
+
test('drop undefined keep null', () => {
|
|
98
|
+
type A = DropMatch<[undefined | null], undefined>
|
|
99
|
+
isType.equal<true, [null], A>()
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
test('drop null keep undefined', () => {
|
|
103
|
+
type A = DropMatch<[undefined | null], null>
|
|
104
|
+
isType.equal<true, [undefined], A>()
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
test('drop both null and undefined', () => {
|
|
108
|
+
type A = DropMatch<[undefined | null], null | undefined>
|
|
109
|
+
isType.equal<true, [], A>()
|
|
110
|
+
|
|
111
|
+
type B = DropMatch<[undefined | null | string], null | undefined>
|
|
112
|
+
isType.equal<true, [string], B>()
|
|
113
|
+
})
|
|
114
|
+
|
|
68
115
|
test('get original if not matched', () => {
|
|
69
116
|
type A = DropMatch<[1], undefined>
|
|
70
117
|
isType.equal<true, [1], A>()
|
|
@@ -111,3 +158,77 @@ describe('DropMatch<A, C>', () => {
|
|
|
111
158
|
})
|
|
112
159
|
})
|
|
113
160
|
})
|
|
161
|
+
|
|
162
|
+
describe('DropUndefined<A>', () => {
|
|
163
|
+
test('drop from array type', () => {
|
|
164
|
+
type A = DropUndefined<Array<string | undefined>>
|
|
165
|
+
isType.equal<true, string[], A>()
|
|
166
|
+
|
|
167
|
+
type B = DropUndefined<Array<string | number>>
|
|
168
|
+
isType.equal<true, Array<string | number>, B>()
|
|
169
|
+
|
|
170
|
+
type C = DropUndefined<Array<string | number | undefined | null>>
|
|
171
|
+
isType.equal<true, Array<string | number | null>, C>()
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
test('drop from tuple type', () => {
|
|
175
|
+
type A = DropUndefined<[string, undefined, number, null]>
|
|
176
|
+
isType.equal<true, [string, number, null], A>()
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
describe('DropNull<A>', () => {
|
|
181
|
+
test('drop from array type', () => {
|
|
182
|
+
type A = DropNull<Array<string | null>>
|
|
183
|
+
isType.equal<true, string[], A>()
|
|
184
|
+
|
|
185
|
+
type B = DropNull<Array<string | number>>
|
|
186
|
+
isType.equal<true, Array<string | number>, B>()
|
|
187
|
+
|
|
188
|
+
type C = DropNull<Array<string | number | undefined | null>>
|
|
189
|
+
isType.equal<true, Array<string | number | undefined>, C>()
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
test('drop from tuple type', () => {
|
|
193
|
+
type A = DropNull<[string, undefined, number, null]>
|
|
194
|
+
isType.equal<true, [string, undefined, number], A>()
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
describe('DropNullable<A>', () => {
|
|
199
|
+
test('drop from array type', () => {
|
|
200
|
+
type A = DropNullable<Array<string | null>>
|
|
201
|
+
isType.equal<true, string[], A>()
|
|
202
|
+
|
|
203
|
+
type B = DropNullable<Array<string | number>>
|
|
204
|
+
isType.equal<true, Array<string | number>, B>()
|
|
205
|
+
|
|
206
|
+
type C = DropNullable<Array<string | number | undefined | null>>
|
|
207
|
+
isType.equal<true, Array<string | number>, C>()
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
test('drop from tuple type', () => {
|
|
211
|
+
type A = DropNullable<[string, undefined, number, null]>
|
|
212
|
+
isType.equal<true, [string, number], A>()
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
describe('drop()', () => {
|
|
218
|
+
test('array', () => {
|
|
219
|
+
const a = drop([1, 'a', 3, 4], 'a')
|
|
220
|
+
expect(a).toEqual([1, 3, 4])
|
|
221
|
+
isType.equal<true, number[], typeof a>()
|
|
222
|
+
})
|
|
223
|
+
test('tuple', () => {
|
|
224
|
+
const a = drop([1, 2, 3, 4] as const, 1 as const)
|
|
225
|
+
expect(a).toEqual([2, 3, 4])
|
|
226
|
+
isType.equal<true, [2, 3, 4], typeof a>()
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
test('drop undefined from tuple', () => {
|
|
230
|
+
const a = drop([1, undefined, 3, undefined, 4] as const, undefined)
|
|
231
|
+
expect(a).toEqual([1, 3, 4])
|
|
232
|
+
isType.equal<true, [1, 3, 4], typeof a>()
|
|
233
|
+
})
|
|
234
|
+
})
|
package/ts/array/drop.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Equal } from '../predicates'
|
|
2
|
+
import { NonNull, NonUndefined } from '../utils'
|
|
3
|
+
|
|
4
|
+
export type DropFirst<A extends any[]> = number extends A['length']
|
|
5
|
+
? A
|
|
6
|
+
: (A['length'] extends 0
|
|
7
|
+
? never[]
|
|
8
|
+
: (A['length'] extends 1
|
|
9
|
+
? never[]
|
|
10
|
+
: (A extends [any, ...infer Tail]
|
|
11
|
+
? Tail
|
|
12
|
+
: never)))
|
|
13
|
+
|
|
14
|
+
export type DropLast<A extends any[]> = number extends A['length']
|
|
15
|
+
? A
|
|
16
|
+
: (A['length'] extends 0
|
|
17
|
+
? never[]
|
|
18
|
+
: (A['length'] extends 1
|
|
19
|
+
? never[]
|
|
20
|
+
: (A extends [...infer Heads, any]
|
|
21
|
+
? Heads
|
|
22
|
+
: never)))
|
|
23
|
+
|
|
24
|
+
type ExcludeUnionOfEmptyTuple<A> = Equal<A, []> extends true ? A : Exclude<A, []>
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* drops entries matching `Criteria` in array or tuple `A`.
|
|
28
|
+
*/
|
|
29
|
+
export type DropMatch<A extends Readonly<Array<any>>, Criteria> = number extends A['length']
|
|
30
|
+
// array
|
|
31
|
+
? (A[0] extends Criteria
|
|
32
|
+
// criteria matches: DropAll<string[], string>
|
|
33
|
+
? never[]
|
|
34
|
+
: (undefined extends Criteria
|
|
35
|
+
? (null extends Criteria
|
|
36
|
+
? Array<NonNullable<A[0]>>
|
|
37
|
+
: Array<NonUndefined<A[0]>>)
|
|
38
|
+
: (null extends Criteria
|
|
39
|
+
? Array<NonNull<A[0]>>
|
|
40
|
+
: (Criteria extends A[0]
|
|
41
|
+
? Array<Exclude<A[0], Criteria>>
|
|
42
|
+
: (A[0] extends Criteria ? A : Array<Exclude<A[0], Criteria>>)))))
|
|
43
|
+
: DropMatchTuple<A, Criteria>
|
|
44
|
+
|
|
45
|
+
type DropMatchTuple<A extends Readonly<Array<any>>, Criteria> = A['length'] extends 0
|
|
46
|
+
// empty tuple
|
|
47
|
+
? A
|
|
48
|
+
: (A extends readonly [infer Head, ...infer Tail]
|
|
49
|
+
? (Tail['length'] extends 0
|
|
50
|
+
// single element tuple
|
|
51
|
+
? (undefined extends Criteria
|
|
52
|
+
? ExcludeUnionOfEmptyTuple<Head extends Criteria ? [] : [Head]>
|
|
53
|
+
: ExcludeUnionOfEmptyTuple<Head extends Criteria ? [] : [Head]>
|
|
54
|
+
)
|
|
55
|
+
// multiple elements
|
|
56
|
+
: (Exclude<Head, Criteria> extends never
|
|
57
|
+
? DropMatch<Tail, Criteria>
|
|
58
|
+
: [Exclude<Head, Criteria>, ...DropMatch<Tail, Criteria>]
|
|
59
|
+
))
|
|
60
|
+
: never[]
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
export type DropNull<A extends Array<any>> = DropMatch<A, null>
|
|
64
|
+
export type DropNullable<A extends Array<any>> = DropMatch<A, null | undefined>
|
|
65
|
+
export type DropUndefined<A extends Array<any>> = DropMatch<A, undefined>
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* drop a particular value from an array
|
|
69
|
+
*/
|
|
70
|
+
export function drop<A extends Readonly<Array<any>>, C>(array: A, value: C): DropMatch<A, C> {
|
|
71
|
+
return array.filter(v => v !== value) as any
|
|
72
|
+
}
|
package/ts/array/index.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export type { CommonKeys, CommonPropKeys } from './CommonPropKeys'
|
|
2
2
|
export type { Concat } from './Concat'
|
|
3
3
|
export type { CreateTuple } from './CreateTuple'
|
|
4
|
-
export
|
|
5
|
-
export type { DropLast } from './DropLast'
|
|
6
|
-
export type { DropMatch } from './DropMatch'
|
|
4
|
+
export * from './drop'
|
|
7
5
|
export type { Filter, KeepMatch } from './Filter'
|
|
8
6
|
export type { FindFirst, First } from './FindFirst'
|
|
9
7
|
export type { FindLast } from './FindLast'
|
|
@@ -19,3 +17,4 @@ export type { Some } from './Some'
|
|
|
19
17
|
export type { Tail } from './Tail'
|
|
20
18
|
export type { PropUnion, UnionOfProps } from './UnionOfProps'
|
|
21
19
|
export type { ArrayValue, UnionOfValues } from './UnionOfValues'
|
|
20
|
+
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isType, literalArray } from '..'
|
|
2
2
|
|
|
3
3
|
test('entries in array are restricted to the input literals', () => {
|
|
4
4
|
const actual = literalArray('a', 'b')
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
const x: (typeof actual[number]) & 'c' = 'c' as never
|
|
8
|
-
|
|
9
|
-
assertType<never>(x)
|
|
6
|
+
isType.equal<true, Array<'a' | 'b'>, typeof actual>()
|
|
10
7
|
})
|
package/ts/object/split.spec.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { isType, split } from '..'
|
|
2
2
|
|
|
3
3
|
const target = { a: 0, b: '', c: false }
|
|
4
|
+
|
|
4
5
|
test('can use undefined as default', () => {
|
|
5
6
|
const [{ a }] = split(target, { a: undefined })
|
|
6
7
|
|
|
7
|
-
isType.equal<true, typeof a
|
|
8
|
+
isType.equal<true, number, typeof a>()
|
|
8
9
|
expect(a).toBe(0)
|
|
9
10
|
})
|
|
10
11
|
|
|
@@ -15,6 +16,52 @@ test('can specify default with the same type', () => {
|
|
|
15
16
|
expect(a).toBe(0)
|
|
16
17
|
})
|
|
17
18
|
|
|
19
|
+
test('specifying default removes undefined and null from the type', () => {
|
|
20
|
+
type S = { a?: number | null, b: number }
|
|
21
|
+
const s: S = { b: 2 }
|
|
22
|
+
|
|
23
|
+
const [{ a }] = split(s, { a: 1 })
|
|
24
|
+
expect(a).toBe(1)
|
|
25
|
+
|
|
26
|
+
isType.equal<true, number, typeof a>()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('can default with null', () => {
|
|
30
|
+
const s: { a?: number | null } = {}
|
|
31
|
+
const [{ a }] = split(s, { a: null })
|
|
32
|
+
|
|
33
|
+
expect(a).toBe(null)
|
|
34
|
+
|
|
35
|
+
isType.equal<true, number | null, typeof a>()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
test('can default with false', () => {
|
|
40
|
+
const s: { a?: number | boolean } = {}
|
|
41
|
+
const [{ a }] = split(s, { a: false })
|
|
42
|
+
|
|
43
|
+
expect(a).toBe(false)
|
|
44
|
+
|
|
45
|
+
isType.equal<true, number | boolean, typeof a>()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('can default with empty string', () => {
|
|
49
|
+
const s: { a?: number | null | string } = {}
|
|
50
|
+
const [{ a }] = split(s, { a: '' })
|
|
51
|
+
|
|
52
|
+
expect(a).toBe('')
|
|
53
|
+
|
|
54
|
+
isType.equal<true, number | string, typeof a>()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('keep falsy value other than undefined and null', () => {
|
|
58
|
+
expect(split({ a: '' }, { a: 'a' })[0].a).toBe('')
|
|
59
|
+
expect(split({ a: false }, { a: true })[0].a).toBe(false)
|
|
60
|
+
|
|
61
|
+
expect(split({ a: null as string | null }, { a: 'a' })[0].a).toBe('a')
|
|
62
|
+
expect(split({ a: undefined as string | undefined }, { a: 'a' })[0].a).toBe('a')
|
|
63
|
+
})
|
|
64
|
+
|
|
18
65
|
test('can specify default as one of the intersect types', () => {
|
|
19
66
|
const [a] = split({ a: undefined as number | string | undefined }, { a: '2' })
|
|
20
67
|
|
package/ts/object/split.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { AnyRecord
|
|
1
|
+
import { AnyRecord } from './AnyRecord'
|
|
2
|
+
import { Omit } from './omit'
|
|
3
|
+
import { reduceByKey } from './reduceKey'
|
|
2
4
|
|
|
3
5
|
type Splitter<T extends AnyRecord> = Partial<{ [k in keyof T]: T[k] | undefined }>
|
|
4
|
-
export type Split<T extends AnyRecord, S extends AnyRecord> = {
|
|
6
|
+
export type Split<T extends AnyRecord, S extends AnyRecord> = {
|
|
7
|
+
[k in keyof S]: S[k] extends undefined ? T[k] : NonNullable<T[k]> | S[k]
|
|
8
|
+
}
|
|
5
9
|
|
|
6
10
|
/**
|
|
7
11
|
* Split an object into multiple objects.
|
|
@@ -189,7 +193,10 @@ export function split<
|
|
|
189
193
|
]
|
|
190
194
|
export function split(target: AnyRecord, ...splitters: AnyRecord[]): AnyRecord[] {
|
|
191
195
|
const keyMap: AnyRecord = {}
|
|
192
|
-
const s = splitters.map(s => reduceByKey(
|
|
196
|
+
const s = splitters.map(s => reduceByKey(
|
|
197
|
+
s,
|
|
198
|
+
(p, k) => (keyMap[k] = true, p[k] = target[k] ?? s[k], p),
|
|
199
|
+
{} as AnyRecord))
|
|
193
200
|
const r = reduceByKey(target, (p, k) => keyMap[k] ? p : (p[k] = target[k], p), {} as AnyRecord)
|
|
194
201
|
return [...s, r]
|
|
195
202
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type NonNull<T> = T extends null ? never : T
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type NonUndefined<T> = T extends undefined ? never : T
|
package/ts/utils/index.ts
CHANGED
package/cjs/array/DropFirst.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare type DropFirst<A extends any[]> = number extends A['length'] ? A : (A['length'] extends 0 ? never[] : (A['length'] extends 1 ? never[] : (A extends [any, ...infer Tail] ? Tail : never)));
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DropFirst.js","sourceRoot":"","sources":["../../ts/array/DropFirst.ts"],"names":[],"mappings":""}
|
package/cjs/array/DropLast.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare type DropLast<A extends any[]> = number extends A['length'] ? A : (A['length'] extends 0 ? never[] : (A['length'] extends 1 ? never[] : (A extends [...infer Heads, any] ? Heads : never)));
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DropLast.js","sourceRoot":"","sources":["../../ts/array/DropLast.ts"],"names":[],"mappings":""}
|
package/cjs/array/DropMatch.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
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 {};
|
package/cjs/array/DropMatch.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DropMatch.js","sourceRoot":"","sources":["../../ts/array/DropMatch.ts"],"names":[],"mappings":""}
|
package/esm/array/DropFirst.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DropFirst.js","sourceRoot":"","sources":["../../ts/array/DropFirst.ts"],"names":[],"mappings":""}
|
package/esm/array/DropLast.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DropLast.js","sourceRoot":"","sources":["../../ts/array/DropLast.ts"],"names":[],"mappings":""}
|
package/esm/array/DropMatch.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DropMatch.js","sourceRoot":"","sources":["../../ts/array/DropMatch.ts"],"names":[],"mappings":""}
|
package/ts/array/DropFirst.ts
DELETED
package/ts/array/DropLast.ts
DELETED
package/ts/array/DropMatch.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
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[]))
|