type-plus 4.6.1 → 4.7.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.
Files changed (63) hide show
  1. package/README.md +5 -0
  2. package/cjs/array/CreateTuple.d.ts +2 -2
  3. package/cjs/array/drop.d.ts +12 -0
  4. package/cjs/array/drop.js +8 -0
  5. package/cjs/array/drop.js.map +1 -0
  6. package/cjs/array/index.d.ts +1 -3
  7. package/cjs/array/index.js +1 -0
  8. package/cjs/array/index.js.map +1 -1
  9. package/cjs/object/split.d.ts +3 -2
  10. package/cjs/object/split.js +3 -3
  11. package/cjs/object/split.js.map +1 -1
  12. package/cjs/testing/stub.d.ts +3 -0
  13. package/cjs/testing/stub.js +8 -0
  14. package/cjs/testing/stub.js.map +1 -1
  15. package/cjs/utils/NonNull.d.ts +1 -0
  16. package/cjs/{array/DropLast.js → utils/NonNull.js} +1 -1
  17. package/cjs/utils/NonNull.js.map +1 -0
  18. package/cjs/utils/NonUndefined.d.ts +1 -0
  19. package/cjs/{array/DropFirst.js → utils/NonUndefined.js} +1 -1
  20. package/cjs/utils/NonUndefined.js.map +1 -0
  21. package/cjs/utils/index.d.ts +2 -0
  22. package/esm/array/drop.js +4 -0
  23. package/esm/array/drop.js.map +1 -0
  24. package/esm/array/index.js +1 -0
  25. package/esm/array/index.js.map +1 -1
  26. package/esm/object/split.js +1 -1
  27. package/esm/object/split.js.map +1 -1
  28. package/esm/testing/stub.js +8 -0
  29. package/esm/testing/stub.js.map +1 -1
  30. package/esm/utils/NonNull.js +2 -0
  31. package/esm/utils/NonNull.js.map +1 -0
  32. package/esm/utils/NonUndefined.js +2 -0
  33. package/esm/utils/NonUndefined.js.map +1 -0
  34. package/package.json +1 -1
  35. package/ts/array/CreateTuple.spec.ts +12 -0
  36. package/ts/array/CreateTuple.ts +4 -4
  37. package/ts/array/DropMatch.spec.ts +124 -3
  38. package/ts/array/drop.ts +72 -0
  39. package/ts/array/index.ts +2 -3
  40. package/ts/array/literalArray.spec.ts +2 -5
  41. package/ts/object/split.spec.ts +48 -1
  42. package/ts/object/split.ts +10 -3
  43. package/ts/testing/stub.spec.ts +44 -24
  44. package/ts/testing/stub.ts +12 -0
  45. package/ts/utils/NonNull.ts +1 -0
  46. package/ts/utils/NonUndefined.ts +1 -0
  47. package/ts/utils/index.ts +2 -0
  48. package/cjs/array/DropFirst.d.ts +0 -1
  49. package/cjs/array/DropFirst.js.map +0 -1
  50. package/cjs/array/DropLast.d.ts +0 -1
  51. package/cjs/array/DropLast.js.map +0 -1
  52. package/cjs/array/DropMatch.d.ts +0 -5
  53. package/cjs/array/DropMatch.js +0 -3
  54. package/cjs/array/DropMatch.js.map +0 -1
  55. package/esm/array/DropFirst.js +0 -2
  56. package/esm/array/DropFirst.js.map +0 -1
  57. package/esm/array/DropLast.js +0 -2
  58. package/esm/array/DropLast.js.map +0 -1
  59. package/esm/array/DropMatch.js +0 -2
  60. package/esm/array/DropMatch.js.map +0 -1
  61. package/ts/array/DropFirst.ts +0 -9
  62. package/ts/array/DropLast.ts +0 -9
  63. 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>`.
@@ -436,6 +440,7 @@ So you may encounter some weird behavior if your logic is complex.
436
440
  - `requiredDeep(...)`: merge options deeply and removing `Partial<T>`. From [`unpartial`](https://github.com/unional/unpartial)
437
441
  - `split(target, ...splitters)`: split one object into multiple objects.
438
442
  - `stub<T>(value)`: stub a particular type `T`.
443
+ - `stub.build<T>(init?)`: build a stub for particular type `T`.
439
444
  - `typeOverrideIncompatible<T>()`: override only the incompatible portion between two types.
440
445
 
441
446
  ```ts
@@ -1,2 +1,2 @@
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;
1
+ import { DigitArray, IsPositive, IsWhole } from '../math';
2
+ export declare type CreateTuple<L extends number, T = any, Fail = never> = number extends L ? T[] : IsPositive<L> extends true ? IsWhole<L> extends true ? DigitArray.ToTuple<[], DigitArray.FromNumber<L>, T> : Fail : Fail;
@@ -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,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.drop = void 0;
4
+ function drop(array, value) {
5
+ return array.filter(function (v) { return v !== value; });
6
+ }
7
+ exports.drop = drop;
8
+ //# sourceMappingURL=drop.js.map
@@ -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"}
@@ -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 type { DropFirst } from './DropFirst';
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';
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/array/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAaA,iDAA8B;AAE9B,gDAA6B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/array/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAGA,yCAAsB;AAQtB,iDAA8B;AAE9B,gDAA6B"}
@@ -1,9 +1,10 @@
1
- import { AnyRecord, Omit } from '..';
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>,
@@ -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 __1 = require("..");
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, __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, __1.reduceByKey)(target, function (p, k) { return keyMap[k] ? p : (p[k] = target[k], p); }, {});
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;
@@ -1 +1 @@
1
- {"version":3,"file":"split.js","sourceRoot":"","sources":["../../ts/object/split.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,wBAAiD;AA6LjD,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,eAAW,EAAC,CAAC,EAAE,UAAC,CAAC,EAAE,CAAC,YAAK,OAAA,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,MAAA,MAAM,CAAC,CAAC,CAAC,mCAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA,EAAA,EAAE,EAAe,CAAC,EAA1F,CAA0F,CAAC,CAAA;IACxH,IAAM,CAAC,GAAG,IAAA,eAAW,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;AALD,sBAKC"}
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"}
@@ -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
+ }
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"stub.js","sourceRoot":"","sources":["../../ts/testing/stub.ts"],"names":[],"mappings":";;;AAOA,SAAgB,IAAI,CAAI,IAAoB;IAC1C,OAAO,IAAS,CAAA;AAClB,CAAC;AAFD,oBAEC"}
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;
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=DropLast.js.map
3
+ //# sourceMappingURL=NonNull.js.map
@@ -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;
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=DropFirst.js.map
3
+ //# sourceMappingURL=NonUndefined.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NonUndefined.js","sourceRoot":"","sources":["../../ts/utils/NonUndefined.ts"],"names":[],"mappings":""}
@@ -1,2 +1,4 @@
1
1
  export * from './as';
2
+ export type { NonNull } from './NonNull';
3
+ export type { NonUndefined } from './NonUndefined';
2
4
  export type { Widen } from './Widen';
@@ -0,0 +1,4 @@
1
+ export function drop(array, value) {
2
+ return array.filter(v => v !== value);
3
+ }
4
+ //# sourceMappingURL=drop.js.map
@@ -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"}
@@ -1,3 +1,4 @@
1
+ export * from './drop';
1
2
  export * from './literalArray';
2
3
  export * from './reduceWhile';
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/array/index.ts"],"names":[],"mappings":"AAaA,cAAc,gBAAgB,CAAA;AAE9B,cAAc,eAAe,CAAA"}
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"}
@@ -1,4 +1,4 @@
1
- import { reduceByKey } from '..';
1
+ import { reduceByKey } from './reduceKey';
2
2
  export function split(target, ...splitters) {
3
3
  const keyMap = {};
4
4
  const s = splitters.map(s => reduceByKey(s, (p, k) => (keyMap[k] = true, p[k] = target[k] ?? s[k], p), {}));
@@ -1 +1 @@
1
- {"version":3,"file":"split.js","sourceRoot":"","sources":["../../ts/object/split.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,WAAW,EAAE,MAAM,IAAI,CAAA;AA6LjD,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,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAe,CAAC,CAAC,CAAA;IACxH,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"}
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"}
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"stub.js","sourceRoot":"","sources":["../../ts/testing/stub.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,IAAI,CAAI,IAAoB;IAC1C,OAAO,IAAS,CAAA;AAClB,CAAC"}
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=NonNull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NonNull.js","sourceRoot":"","sources":["../../ts/utils/NonNull.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=NonUndefined.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NonUndefined.js","sourceRoot":"","sources":["../../ts/utils/NonUndefined.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-plus",
3
- "version": "4.6.1",
3
+ "version": "4.7.0",
4
4
  "description": "Provides additional types for TypeScript.",
5
5
  "homepage": "https://github.com/unional/type-plus",
6
6
  "bugs": {
@@ -32,3 +32,15 @@ test('L = number gets array', () => {
32
32
  type A = CreateTuple<number, 1>
33
33
  isType.equal<true, 1[], A>()
34
34
  })
35
+
36
+ test('Non whole number gets never', () => {
37
+ type A = CreateTuple<1.2>
38
+
39
+ isType.equal<true, never, A>()
40
+ })
41
+
42
+ test('can specify fail type', () => {
43
+ type A = CreateTuple<1.2, 1, null>
44
+
45
+ isType.equal<true, null, A>()
46
+ })
@@ -1,4 +1,4 @@
1
- import { DigitArray, IsPositive } from '../math'
1
+ import { DigitArray, IsPositive, IsWhole } from '../math'
2
2
 
3
3
  /**
4
4
  * Creates `Tuple<T>` with `L` number of elements.
@@ -6,7 +6,7 @@ import { DigitArray, IsPositive } from '../math'
6
6
  * @see https://github.com/microsoft/TypeScript/issues/26223#issuecomment-674514787
7
7
  * @see https://github.com/microsoft/TypeScript/issues/47874#issuecomment-1039157322
8
8
  */
9
- export type CreateTuple<L extends number, T = any> =
10
- number extends L ? T[] : IsPositive<L> extends true
9
+ export type CreateTuple<L extends number, T = any, Fail = never> =
10
+ number extends L ? T[] : IsPositive<L> extends true ? IsWhole<L> extends true
11
11
  ? DigitArray.ToTuple<[], DigitArray.FromNumber<L>, T>
12
- : never
12
+ : Fail : Fail
@@ -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
+ })
@@ -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 type { DropFirst } from './DropFirst'
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 { assertType, literalArray } from '..'
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
- // the cast is just for assignment. Does not affect type.
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
  })
@@ -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, number | undefined>()
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
 
@@ -1,7 +1,11 @@
1
- import { AnyRecord, Omit, reduceByKey } from '..'
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> = { [k in keyof S]: NonNullable<T[k]> | S[k] }
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(s, (p, k) => (keyMap[k] = true, p[k] = target[k] ?? s[k], p), {} as AnyRecord))
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
  }
@@ -1,38 +1,58 @@
1
1
  import { isType, stub } from '..'
2
2
 
3
- test('stub is a partial of the actual object', () => {
4
- const real = { a: 1, b: { c: 2 }, d: 3 }
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
- const a = stub<typeof real>({ a: 2 })
7
- expect(a.a).toBe(2)
8
- isType.equal<true, typeof a, typeof real>()
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
- test('stub function retains param types', () => {
12
- function real(a: string, b: number): boolean { return a === String(b) }
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
- const a = stub<typeof real>((_a, _b) => {
15
- isType.equal<true, string, typeof _a>()
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
- expect(a('1', 1)).toBe(false)
21
- isType.equal<true, typeof a, typeof real>()
22
- })
25
+ test('stub function params can be omitted', () => {
26
+ function real(a: string, b: number): boolean { return a === String(b) }
23
27
 
24
- test('stub function params can be omitted', () => {
25
- function real(a: string, b: number): boolean { return a === String(b) }
28
+ const a = stub<typeof real>(() => false)
26
29
 
27
- const a = stub<typeof real>(() => false)
30
+ expect(a('1', 1)).toBe(false)
31
+ isType.equal<true, typeof a, typeof real>()
32
+ })
28
33
 
29
- expect(a('1', 1)).toBe(false)
30
- isType.equal<true, typeof a, typeof real>()
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
- test('stub input can be omitted', () => {
34
- const real = { a: 1, b: { c: 2 }, d: 3 }
42
+ describe('stub.build()', () => {
43
+ test('build a stub function', () => {
44
+ const real = { a: 1, b: { c: 2 }, d: 3 }
35
45
 
36
- const a = stub<typeof real>()
37
- isType.equal<true, typeof a, typeof real>()
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
  })
@@ -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/index.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  export * from './as'
2
+ export type { NonNull } from './NonNull'
3
+ export type { NonUndefined } from './NonUndefined'
2
4
  export type { Widen } from './Widen'
@@ -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":""}
@@ -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":""}
@@ -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 {};
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=DropMatch.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DropMatch.js","sourceRoot":"","sources":["../../ts/array/DropMatch.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=DropFirst.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DropFirst.js","sourceRoot":"","sources":["../../ts/array/DropFirst.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=DropLast.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DropLast.js","sourceRoot":"","sources":["../../ts/array/DropLast.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=DropMatch.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DropMatch.js","sourceRoot":"","sources":["../../ts/array/DropMatch.ts"],"names":[],"mappings":""}
@@ -1,9 +0,0 @@
1
- export type DropFirst<A extends any[]> = number extends A['length']
2
- ? A
3
- : (A['length'] extends 0
4
- ? never[]
5
- : (A['length'] extends 1
6
- ? never[]
7
- : (A extends [any, ...infer Tail]
8
- ? Tail
9
- : never)))
@@ -1,9 +0,0 @@
1
- export type DropLast<A extends any[]> = number extends A['length']
2
- ? A
3
- : (A['length'] extends 0
4
- ? never[]
5
- : (A['length'] extends 1
6
- ? never[]
7
- : (A extends [...infer Heads, any]
8
- ? Heads
9
- : never)))
@@ -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[]))