type-plus 4.6.2 → 4.8.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 +6 -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/testing/stub.d.ts +3 -0
- package/cjs/testing/stub.js +8 -0
- package/cjs/testing/stub.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/as.d.ts +4 -0
- package/cjs/utils/as.js +8 -1
- package/cjs/utils/as.js.map +1 -1
- 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/testing/stub.js +8 -0
- package/esm/testing/stub.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/esm/utils/as.js +6 -0
- package/esm/utils/as.js.map +1 -1
- 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/testing/stub.spec.ts +44 -24
- package/ts/testing/stub.ts +12 -0
- package/ts/utils/NonNull.ts +1 -0
- package/ts/utils/NonUndefined.ts +1 -0
- package/ts/utils/as.spec.ts +13 -1
- package/ts/utils/as.ts +10 -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>`.
|
|
@@ -423,6 +427,7 @@ So you may encounter some weird behavior if your logic is complex.
|
|
|
423
427
|
|
|
424
428
|
### Utility Functions
|
|
425
429
|
|
|
430
|
+
- `amend(subject)...`: amend subject as union or intersect of `T`.
|
|
426
431
|
- `facade(subject, ...props)`: create a facade of `subject`.
|
|
427
432
|
- `getField(subject, key, defaultValue)`: get a field from a subject. Works against nullable and optional subject.
|
|
428
433
|
- `hasKey()`: function of `HasKey`.
|
|
@@ -436,6 +441,7 @@ So you may encounter some weird behavior if your logic is complex.
|
|
|
436
441
|
- `requiredDeep(...)`: merge options deeply and removing `Partial<T>`. From [`unpartial`](https://github.com/unional/unpartial)
|
|
437
442
|
- `split(target, ...splitters)`: split one object into multiple objects.
|
|
438
443
|
- `stub<T>(value)`: stub a particular type `T`.
|
|
444
|
+
- `stub.build<T>(init?)`: build a stub for particular type `T`.
|
|
439
445
|
- `typeOverrideIncompatible<T>()`: override only the incompatible portion between two types.
|
|
440
446
|
|
|
441
447
|
```ts
|
|
@@ -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"}
|
package/cjs/testing/stub.d.ts
CHANGED
|
@@ -4,3 +4,6 @@ export declare namespace stub {
|
|
|
4
4
|
type Param<T> = T extends AnyFunction ? T : RecursivePartial<T>;
|
|
5
5
|
}
|
|
6
6
|
export declare function stub<T>(stub?: stub.Param<T>): T;
|
|
7
|
+
export declare namespace stub {
|
|
8
|
+
var build: <T>(init?: Param<T> | undefined) => (value?: Param<T> | undefined) => T;
|
|
9
|
+
}
|
package/cjs/testing/stub.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.stub = void 0;
|
|
4
|
+
var unpartial_1 = require("unpartial");
|
|
4
5
|
function stub(stub) {
|
|
5
6
|
return stub;
|
|
6
7
|
}
|
|
7
8
|
exports.stub = stub;
|
|
9
|
+
stub.build = function build(init) {
|
|
10
|
+
return function (value) {
|
|
11
|
+
return init
|
|
12
|
+
? stub((0, unpartial_1.requiredDeep)(init, value))
|
|
13
|
+
: stub(value);
|
|
14
|
+
};
|
|
15
|
+
};
|
|
8
16
|
//# sourceMappingURL=stub.js.map
|
package/cjs/testing/stub.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub.js","sourceRoot":"","sources":["../../ts/testing/stub.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"stub.js","sourceRoot":"","sources":["../../ts/testing/stub.ts"],"names":[],"mappings":";;;AAAA,uCAAwC;AAQxC,SAAgB,IAAI,CAAI,IAAoB;IAC1C,OAAO,IAAS,CAAA;AAClB,CAAC;AAFD,oBAEC;AAKD,IAAI,CAAC,KAAK,GAAG,SAAS,KAAK,CAAI,IAAoB;IACjD,OAAO,UAAU,KAAqB;QACpC,OAAO,IAAI;YACT,CAAC,CAAC,IAAI,CAAI,IAAA,wBAAY,EAAC,IAAW,EAAE,KAAY,CAAQ,CAAC;YACzD,CAAC,CAAC,IAAI,CAAI,KAAK,CAAC,CAAA;IACpB,CAAC,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -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/as.d.ts
CHANGED
package/cjs/utils/as.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.asAny = exports.as = void 0;
|
|
3
|
+
exports.amend = exports.asAny = exports.as = void 0;
|
|
4
4
|
function as(subject) {
|
|
5
5
|
return subject;
|
|
6
6
|
}
|
|
@@ -9,4 +9,11 @@ function asAny(subject) {
|
|
|
9
9
|
return subject;
|
|
10
10
|
}
|
|
11
11
|
exports.asAny = asAny;
|
|
12
|
+
function amend(subject) {
|
|
13
|
+
return {
|
|
14
|
+
union: function () { return subject; },
|
|
15
|
+
intersect: function () { return subject; }
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
exports.amend = amend;
|
|
12
19
|
//# sourceMappingURL=as.js.map
|
package/cjs/utils/as.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"as.js","sourceRoot":"","sources":["../../ts/utils/as.ts"],"names":[],"mappings":";;;AAAA,SAAgB,EAAE,CAAI,OAAgB;IACpC,OAAO,OAAY,CAAA;AACrB,CAAC;AAFD,gBAEC;AAED,SAAgB,KAAK,CAAC,OAAgB;IACpC,OAAO,OAAO,CAAA;AAChB,CAAC;AAFD,sBAEC"}
|
|
1
|
+
{"version":3,"file":"as.js","sourceRoot":"","sources":["../../ts/utils/as.ts"],"names":[],"mappings":";;;AAAA,SAAgB,EAAE,CAAI,OAAgB;IACpC,OAAO,OAAY,CAAA;AACrB,CAAC;AAFD,gBAEC;AAED,SAAgB,KAAK,CAAC,OAAgB;IACpC,OAAO,OAAO,CAAA;AAChB,CAAC;AAFD,sBAEC;AAKD,SAAgB,KAAK,CAAI,OAAU;IACjC,OAAO;QACL,KAAK,EAAL,cAAoB,OAAO,OAAgB,CAAA,CAAC,CAAC;QAC7C,SAAS,EAAT,cAAwB,OAAO,OAAgB,CAAA,CAAC,CAAC;KAClD,CAAA;AACH,CAAC;AALD,sBAKC"}
|
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"}
|
package/esm/testing/stub.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
+
import { requiredDeep } from 'unpartial';
|
|
1
2
|
export function stub(stub) {
|
|
2
3
|
return stub;
|
|
3
4
|
}
|
|
5
|
+
stub.build = function build(init) {
|
|
6
|
+
return function (value) {
|
|
7
|
+
return init
|
|
8
|
+
? stub(requiredDeep(init, value))
|
|
9
|
+
: stub(value);
|
|
10
|
+
};
|
|
11
|
+
};
|
|
4
12
|
//# sourceMappingURL=stub.js.map
|
package/esm/testing/stub.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub.js","sourceRoot":"","sources":["../../ts/testing/stub.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stub.js","sourceRoot":"","sources":["../../ts/testing/stub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAQxC,MAAM,UAAU,IAAI,CAAI,IAAoB;IAC1C,OAAO,IAAS,CAAA;AAClB,CAAC;AAKD,IAAI,CAAC,KAAK,GAAG,SAAS,KAAK,CAAI,IAAoB;IACjD,OAAO,UAAU,KAAqB;QACpC,OAAO,IAAI;YACT,CAAC,CAAC,IAAI,CAAI,YAAY,CAAC,IAAW,EAAE,KAAY,CAAQ,CAAC;YACzD,CAAC,CAAC,IAAI,CAAI,KAAK,CAAC,CAAA;IACpB,CAAC,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -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/esm/utils/as.js
CHANGED
package/esm/utils/as.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"as.js","sourceRoot":"","sources":["../../ts/utils/as.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,EAAE,CAAI,OAAgB;IACpC,OAAO,OAAY,CAAA;AACrB,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,OAAgB;IACpC,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
|
1
|
+
{"version":3,"file":"as.js","sourceRoot":"","sources":["../../ts/utils/as.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,EAAE,CAAI,OAAgB;IACpC,OAAO,OAAY,CAAA;AACrB,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,OAAgB;IACpC,OAAO,OAAO,CAAA;AAChB,CAAC;AAKD,MAAM,UAAU,KAAK,CAAI,OAAU;IACjC,OAAO;QACL,KAAK,KAAe,OAAO,OAAgB,CAAA,CAAC,CAAC;QAC7C,SAAS,KAAe,OAAO,OAAgB,CAAA,CAAC,CAAC;KAClD,CAAA;AACH,CAAC"}
|
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
|
}
|
package/ts/testing/stub.spec.ts
CHANGED
|
@@ -1,38 +1,58 @@
|
|
|
1
1
|
import { isType, stub } from '..'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
describe('stub()', () => {
|
|
4
|
+
test('stub is a partial of the actual object', () => {
|
|
5
|
+
const real = { a: 1, b: { c: 2 }, d: 3 }
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
})
|
|
7
|
+
const a = stub<typeof real>({ a: 2 })
|
|
8
|
+
expect(a.a).toBe(2)
|
|
9
|
+
isType.equal<true, typeof a, typeof real>()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('stub function retains param types', () => {
|
|
13
|
+
function real(a: string, b: number): boolean { return a === String(b) }
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
const a = stub<typeof real>((_a, _b) => {
|
|
16
|
+
isType.equal<true, string, typeof _a>()
|
|
17
|
+
isType.equal<true, number, typeof _b>()
|
|
18
|
+
return false
|
|
19
|
+
})
|
|
13
20
|
|
|
14
|
-
|
|
15
|
-
isType.equal<true,
|
|
16
|
-
isType.equal<true, number, typeof _b>()
|
|
17
|
-
return false
|
|
21
|
+
expect(a('1', 1)).toBe(false)
|
|
22
|
+
isType.equal<true, typeof a, typeof real>()
|
|
18
23
|
})
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
})
|
|
25
|
+
test('stub function params can be omitted', () => {
|
|
26
|
+
function real(a: string, b: number): boolean { return a === String(b) }
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
function real(a: string, b: number): boolean { return a === String(b) }
|
|
28
|
+
const a = stub<typeof real>(() => false)
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
expect(a('1', 1)).toBe(false)
|
|
31
|
+
isType.equal<true, typeof a, typeof real>()
|
|
32
|
+
})
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
test('stub input can be omitted', () => {
|
|
35
|
+
const real = { a: 1, b: { c: 2 }, d: 3 }
|
|
36
|
+
|
|
37
|
+
const a = stub<typeof real>()
|
|
38
|
+
isType.equal<true, typeof a, typeof real>()
|
|
39
|
+
})
|
|
31
40
|
})
|
|
32
41
|
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
describe('stub.build()', () => {
|
|
43
|
+
test('build a stub function', () => {
|
|
44
|
+
const real = { a: 1, b: { c: 2 }, d: 3 }
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
const s = stub.build<typeof real>()
|
|
47
|
+
const a = s({ a: 2 })
|
|
48
|
+
expect(a.a).toBe(2)
|
|
49
|
+
isType.equal<true, typeof a, typeof real>()
|
|
50
|
+
})
|
|
51
|
+
test('can define init value', () => {
|
|
52
|
+
type S = { a: number, b: string }
|
|
53
|
+
const s = stub.build<S>({ b: 'b' })
|
|
54
|
+
const a = s({ a: 1 })
|
|
55
|
+
expect(a).toEqual({ a: 1, b: 'b' })
|
|
56
|
+
isType.equal<true, S, typeof a>()
|
|
57
|
+
})
|
|
38
58
|
})
|
package/ts/testing/stub.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { requiredDeep } from 'unpartial'
|
|
1
2
|
import { AnyFunction } from '../function'
|
|
2
3
|
import { RecursivePartial } from '../object'
|
|
3
4
|
|
|
@@ -8,3 +9,14 @@ export namespace stub {
|
|
|
8
9
|
export function stub<T>(stub?: stub.Param<T>) {
|
|
9
10
|
return stub as T
|
|
10
11
|
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* builds a stub function
|
|
15
|
+
*/
|
|
16
|
+
stub.build = function build<T>(init?: stub.Param<T>) {
|
|
17
|
+
return function (value?: stub.Param<T>) {
|
|
18
|
+
return init
|
|
19
|
+
? stub<T>(requiredDeep(init as any, value as any) as any)
|
|
20
|
+
: stub<T>(value)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -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/as.spec.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { as, asAny, isType } from '..'
|
|
1
|
+
import { amend, as, asAny, isType } from '..'
|
|
2
2
|
|
|
3
3
|
describe('as<T>()', () => {
|
|
4
4
|
test('defaults subject type to unknown', () => {
|
|
@@ -31,3 +31,15 @@ describe('asAny()', () => {
|
|
|
31
31
|
})
|
|
32
32
|
})
|
|
33
33
|
|
|
34
|
+
describe('amend<T>()', () => {
|
|
35
|
+
test('assert subject as (subject & T)', () => {
|
|
36
|
+
const s = { a: 1 }
|
|
37
|
+
const a = amend(s).union<{ b: string }>()
|
|
38
|
+
isType.equal<true, { a: number } & { b: string }, typeof a>()
|
|
39
|
+
})
|
|
40
|
+
test('assert subject as (subject | T)', () => {
|
|
41
|
+
const s = { a: 1 }
|
|
42
|
+
const a = amend(s).intersect<{ b: string }>()
|
|
43
|
+
isType.equal<true, { a: number } | { b: string }, typeof a>()
|
|
44
|
+
})
|
|
45
|
+
})
|
package/ts/utils/as.ts
CHANGED
|
@@ -5,3 +5,13 @@ export function as<T>(subject: unknown): T {
|
|
|
5
5
|
export function asAny(subject: unknown): any {
|
|
6
6
|
return subject
|
|
7
7
|
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* amend `subject` with type `T`
|
|
11
|
+
*/
|
|
12
|
+
export function amend<S>(subject: S) {
|
|
13
|
+
return {
|
|
14
|
+
union<T>(): T & S { return subject as T & S },
|
|
15
|
+
intersect<T>(): T | S { return subject as T | S }
|
|
16
|
+
}
|
|
17
|
+
}
|
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[]))
|