type-plus 5.3.0 → 5.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -564,6 +564,20 @@ nominalMatch(b1, b2) // false
564
564
  - `ChainFn<T>: T`: chain function that returns the input type.
565
565
  - `compose(...fns): F`: compose functions
566
566
 
567
+ ## Context Builder
568
+
569
+ - `context()`: a context builder. This is useful to build context for functional programming.\
570
+ It is a sync version of the `AsyncContext` from [async-fp](https://unional/async-fp).
571
+
572
+ ```ts
573
+ import { context } from 'type-plus'
574
+
575
+ // { a: 1, b: 2 }
576
+ const ctx = context({ a: 1 })
577
+ .extend(c => ({ b: c.a + 1 }))
578
+ .build()
579
+ ```
580
+
567
581
  ## Attribution
568
582
 
569
583
  Some code in this library is created by other people in the TypeScript community.
@@ -22,9 +22,9 @@ export declare namespace assertType {
22
22
  var noFalse: <S>(subject: Exclude<S, false>) => void;
23
23
  var isString: (subject: string) => asserts subject is string;
24
24
  var noString: <S>(subject: Exclude<S, string>) => void;
25
- var isFunction: (subject: AnyFunction) => asserts subject is AnyFunction;
26
- var noFunction: <S>(subject: Exclude<S, AnyFunction>) => void;
27
- var isConstructor: (subject: AnyConstructor) => asserts subject is AnyConstructor;
25
+ var isFunction: (subject: AnyFunction<any[], any>) => asserts subject is AnyFunction<any[], any>;
26
+ var noFunction: <S>(subject: Exclude<S, AnyFunction<any[], any>>) => void;
27
+ var isConstructor: (subject: AnyConstructor<any[]>) => asserts subject is AnyConstructor<any[]>;
28
28
  var isError: (subject: Error) => asserts subject is Error;
29
29
  var noError: <S>(subject: Exclude<S, Error>) => void;
30
30
  var isNever: (subject: never) => asserts subject is never;
@@ -0,0 +1,36 @@
1
+ import type { LeftJoin } from '../object/index.js';
2
+ export type ContextBaseShape = Record<string | symbol, any>;
3
+ /**
4
+ * Extends the context with new props.
5
+ * @param context the current context.
6
+ * @return an additional context with new properties.
7
+ */
8
+ export type ContextExtender<Current, Additional> = (context: Current) => Additional;
9
+ export type ContextBuilder<Init extends ContextBaseShape, Ctx extends ContextBaseShape> = {
10
+ /**
11
+ * Extends the context using an extender.
12
+ * @param extender function that add new props to the context.
13
+ *
14
+ * The extender only need to return a new object with new properties.
15
+ *
16
+ * Do not need to merge the existing context with the new props.
17
+ * The builder will do that for you.
18
+ */
19
+ extend<Current extends ContextBaseShape = Ctx, Additional extends ContextBaseShape = ContextBaseShape>(extender: ContextExtender<Current, Additional>): ContextBuilder<Init, LeftJoin<Ctx, Additional>>;
20
+ /**
21
+ * Build and return the context.
22
+ */
23
+ build(): Ctx;
24
+ };
25
+ /**
26
+ * A fluent context builder.
27
+ *
28
+ * The initializer and transformer
29
+ *
30
+ * @param init The initial context or an context initializer.
31
+ * @return the context builder where you can
32
+ * use `extend()` to add context, and
33
+ * use `build()` to build the context.
34
+ */
35
+ export declare function context<Init extends ContextBaseShape, Ctx extends ContextBaseShape = Init>(init?: Init | (() => Init)): ContextBuilder<Init, Ctx>;
36
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../ts/functional/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAElD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,CAAA;AAE3D;;;;GAIG;AACH,MAAM,MAAM,eAAe,CACzB,OAAO,EACP,UAAU,IACR,CAAC,OAAO,EAAE,OAAO,KAAK,UAAU,CAAA;AAEpC,MAAM,MAAM,cAAc,CACxB,IAAI,SAAS,gBAAgB,EAC7B,GAAG,SAAS,gBAAgB,IAC1B;IACF;;;;;;;;OAQG;IACH,MAAM,CACJ,OAAO,SAAS,gBAAgB,GAAG,GAAG,EACtC,UAAU,SAAS,gBAAgB,GAAG,gBAAgB,EACtD,QAAQ,EAAE,eAAe,CAAC,OAAO,EAAE,UAAU,CAAC,GAC5C,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;IACpD;;OAEG;IACH,KAAK,IAAI,GAAG,CAAA;CACb,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CACrB,IAAI,SAAS,gBAAgB,EAC7B,GAAG,SAAS,gBAAgB,GAAG,IAAI,EACnC,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAKvD"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.context = void 0;
15
+ /**
16
+ * A fluent context builder.
17
+ *
18
+ * The initializer and transformer
19
+ *
20
+ * @param init The initial context or an context initializer.
21
+ * @return the context builder where you can
22
+ * use `extend()` to add context, and
23
+ * use `build()` to build the context.
24
+ */
25
+ function context(init) {
26
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
27
+ return typeof init === 'function'
28
+ ? contextBuilder({}, [init])
29
+ : contextBuilder(init !== null && init !== void 0 ? init : {}, []);
30
+ }
31
+ exports.context = context;
32
+ function contextBuilder(init, transformers) {
33
+ return {
34
+ extend: function (transformer) {
35
+ return contextBuilder(init, transformers.concat(transformer));
36
+ },
37
+ build: function () {
38
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
39
+ return transformers.reduce(function (p, t) { return (__assign(__assign({}, p), t(p))); }, init);
40
+ }
41
+ };
42
+ }
43
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../ts/functional/context.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAsCA;;;;;;;;;GASG;AACH,SAAgB,OAAO,CAGrB,IAA0B;IAC1B,+DAA+D;IAC/D,OAAO,OAAO,IAAI,KAAK,UAAU;QAC/B,CAAC,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,cAAc,CAAC,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,EAAE,EAAE,EAAE,CAAQ,CAAA;AAC3C,CAAC;AARD,0BAQC;AAED,SAAS,cAAc,CAAC,IAAsB,EAAE,YAAyC;IACvF,OAAO;QACL,MAAM,YAAC,WAAsC;YAC3C,OAAO,cAAc,CAAC,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAA;QAC/D,CAAC;QACD,KAAK;YACH,+DAA+D;YAC/D,OAAO,YAAY,CAAC,MAAM,CAAC,UAAC,CAAC,EAAE,CAAC,IAAK,OAAA,uBAAM,CAAC,GAAK,CAAC,CAAC,CAAC,CAAC,EAAG,EAAnB,CAAmB,EAAE,IAAI,CAAC,CAAA;QACjE,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=context.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.spec.d.ts","sourceRoot":"","sources":["../../ts/functional/context.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var index_js_1 = require("../index.js");
4
+ describe("".concat(index_js_1.context.name, "()"), function () {
5
+ it('allows no param', function () {
6
+ var r = (0, index_js_1.context)().build();
7
+ expect(r).toEqual({});
8
+ });
9
+ it('accepts an initial context value', function () {
10
+ var r = (0, index_js_1.context)({ a: 1 }).build();
11
+ index_js_1.isType.equal();
12
+ expect(r).toEqual({ a: 1 });
13
+ });
14
+ it('accepts an initializer', function () {
15
+ var r = (0, index_js_1.context)(function () { return ({ a: 1 }); }).build();
16
+ index_js_1.isType.equal();
17
+ expect(r).toEqual({ a: 1 });
18
+ });
19
+ it('accepts transformer expecting Init', function () {
20
+ var r = (0, index_js_1.context)({ a: 1 })
21
+ .extend(function (ctx) {
22
+ index_js_1.isType.equal();
23
+ expect(ctx).toEqual({ a: 1 });
24
+ return { b: ctx.a + 1 };
25
+ })
26
+ .build();
27
+ index_js_1.isType.equal();
28
+ expect(r).toEqual({ a: 1, b: 2 });
29
+ });
30
+ it('provides the combined context to the next transformer', function () {
31
+ var r = (0, index_js_1.context)({ a: 1 })
32
+ .extend(function (ctx) { return ({ b: ctx.a + 1 }); })
33
+ .extend(function (ctx) { return ({ c: ctx.a + ctx.b }); })
34
+ .build();
35
+ index_js_1.isType.equal();
36
+ expect(r).toEqual({ a: 1, b: 2, c: 3 });
37
+ });
38
+ it('accepts extenders needing partial of current context', function () {
39
+ function foo(ctx) {
40
+ return { c: ctx.a + 2 };
41
+ }
42
+ var r = (0, index_js_1.context)({ a: 1, b: 2 }).extend(foo).build();
43
+ index_js_1.isType.equal();
44
+ expect(r).toEqual({ a: 1, b: 2, c: 3 });
45
+ });
46
+ });
47
+ //# sourceMappingURL=context.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.spec.js","sourceRoot":"","sources":["../../ts/functional/context.spec.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  export type { ChainFn, EndoFn } from './ChainFn.js';
2
2
  export * from './compose.js';
3
+ export * from './context.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ts/functional/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACnD,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ts/functional/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACnD,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA"}
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./compose.js"), exports);
18
+ __exportStar(require("./context.js"), exports);
18
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/functional/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAEA,+CAA4B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/functional/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAEA,+CAA4B;AAC5B,+CAA4B"}
@@ -10,6 +10,6 @@ export declare function isType<T>(subject: unknown, validator: (s: T) => unknown
10
10
  export declare namespace isType {
11
11
  var t: <T extends true>(subject?: T | undefined) => boolean;
12
12
  var f: <T extends false>(subject?: T | undefined) => boolean;
13
- var equal: <C extends Equal<A, B>, A, B>() => void;
13
+ var equal: <C extends Equal<A, B, true, false>, A, B>() => void;
14
14
  }
15
15
  //# sourceMappingURL=isType.d.ts.map
@@ -22,9 +22,9 @@ export declare namespace assertType {
22
22
  var noFalse: <S>(subject: Exclude<S, false>) => void;
23
23
  var isString: (subject: string) => asserts subject is string;
24
24
  var noString: <S>(subject: Exclude<S, string>) => void;
25
- var isFunction: (subject: AnyFunction) => asserts subject is AnyFunction;
26
- var noFunction: <S>(subject: Exclude<S, AnyFunction>) => void;
27
- var isConstructor: (subject: AnyConstructor) => asserts subject is AnyConstructor;
25
+ var isFunction: (subject: AnyFunction<any[], any>) => asserts subject is AnyFunction<any[], any>;
26
+ var noFunction: <S>(subject: Exclude<S, AnyFunction<any[], any>>) => void;
27
+ var isConstructor: (subject: AnyConstructor<any[]>) => asserts subject is AnyConstructor<any[]>;
28
28
  var isError: (subject: Error) => asserts subject is Error;
29
29
  var noError: <S>(subject: Exclude<S, Error>) => void;
30
30
  var isNever: (subject: never) => asserts subject is never;
@@ -0,0 +1,36 @@
1
+ import type { LeftJoin } from '../object/index.js';
2
+ export type ContextBaseShape = Record<string | symbol, any>;
3
+ /**
4
+ * Extends the context with new props.
5
+ * @param context the current context.
6
+ * @return an additional context with new properties.
7
+ */
8
+ export type ContextExtender<Current, Additional> = (context: Current) => Additional;
9
+ export type ContextBuilder<Init extends ContextBaseShape, Ctx extends ContextBaseShape> = {
10
+ /**
11
+ * Extends the context using an extender.
12
+ * @param extender function that add new props to the context.
13
+ *
14
+ * The extender only need to return a new object with new properties.
15
+ *
16
+ * Do not need to merge the existing context with the new props.
17
+ * The builder will do that for you.
18
+ */
19
+ extend<Current extends ContextBaseShape = Ctx, Additional extends ContextBaseShape = ContextBaseShape>(extender: ContextExtender<Current, Additional>): ContextBuilder<Init, LeftJoin<Ctx, Additional>>;
20
+ /**
21
+ * Build and return the context.
22
+ */
23
+ build(): Ctx;
24
+ };
25
+ /**
26
+ * A fluent context builder.
27
+ *
28
+ * The initializer and transformer
29
+ *
30
+ * @param init The initial context or an context initializer.
31
+ * @return the context builder where you can
32
+ * use `extend()` to add context, and
33
+ * use `build()` to build the context.
34
+ */
35
+ export declare function context<Init extends ContextBaseShape, Ctx extends ContextBaseShape = Init>(init?: Init | (() => Init)): ContextBuilder<Init, Ctx>;
36
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../ts/functional/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAElD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,CAAA;AAE3D;;;;GAIG;AACH,MAAM,MAAM,eAAe,CACzB,OAAO,EACP,UAAU,IACR,CAAC,OAAO,EAAE,OAAO,KAAK,UAAU,CAAA;AAEpC,MAAM,MAAM,cAAc,CACxB,IAAI,SAAS,gBAAgB,EAC7B,GAAG,SAAS,gBAAgB,IAC1B;IACF;;;;;;;;OAQG;IACH,MAAM,CACJ,OAAO,SAAS,gBAAgB,GAAG,GAAG,EACtC,UAAU,SAAS,gBAAgB,GAAG,gBAAgB,EACtD,QAAQ,EAAE,eAAe,CAAC,OAAO,EAAE,UAAU,CAAC,GAC5C,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;IACpD;;OAEG;IACH,KAAK,IAAI,GAAG,CAAA;CACb,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CACrB,IAAI,SAAS,gBAAgB,EAC7B,GAAG,SAAS,gBAAgB,GAAG,IAAI,EACnC,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAKvD"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * A fluent context builder.
3
+ *
4
+ * The initializer and transformer
5
+ *
6
+ * @param init The initial context or an context initializer.
7
+ * @return the context builder where you can
8
+ * use `extend()` to add context, and
9
+ * use `build()` to build the context.
10
+ */
11
+ export function context(init) {
12
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
13
+ return typeof init === 'function'
14
+ ? contextBuilder({}, [init])
15
+ : contextBuilder(init ?? {}, []);
16
+ }
17
+ function contextBuilder(init, transformers) {
18
+ return {
19
+ extend(transformer) {
20
+ return contextBuilder(init, transformers.concat(transformer));
21
+ },
22
+ build() {
23
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
24
+ return transformers.reduce((p, t) => ({ ...p, ...t(p) }), init);
25
+ }
26
+ };
27
+ }
28
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../ts/functional/context.ts"],"names":[],"mappings":"AAsCA;;;;;;;;;GASG;AACH,MAAM,UAAU,OAAO,CAGrB,IAA0B;IAC1B,+DAA+D;IAC/D,OAAO,OAAO,IAAI,KAAK,UAAU;QAC/B,CAAC,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,cAAc,CAAC,IAAI,IAAI,EAAE,EAAE,EAAE,CAAQ,CAAA;AAC3C,CAAC;AAED,SAAS,cAAc,CAAC,IAAsB,EAAE,YAAyC;IACvF,OAAO;QACL,MAAM,CAAC,WAAsC;YAC3C,OAAO,cAAc,CAAC,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAA;QAC/D,CAAC;QACD,KAAK;YACH,+DAA+D;YAC/D,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;QACjE,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=context.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.spec.d.ts","sourceRoot":"","sources":["../../ts/functional/context.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ import { context, isType } from '../index.js';
2
+ describe(`${context.name}()`, () => {
3
+ it('allows no param', () => {
4
+ const r = context().build();
5
+ expect(r).toEqual({});
6
+ });
7
+ it('accepts an initial context value', () => {
8
+ const r = context({ a: 1 }).build();
9
+ isType.equal();
10
+ expect(r).toEqual({ a: 1 });
11
+ });
12
+ it('accepts an initializer', () => {
13
+ const r = context(() => ({ a: 1 })).build();
14
+ isType.equal();
15
+ expect(r).toEqual({ a: 1 });
16
+ });
17
+ it('accepts transformer expecting Init', () => {
18
+ const r = context({ a: 1 })
19
+ .extend(ctx => {
20
+ isType.equal();
21
+ expect(ctx).toEqual({ a: 1 });
22
+ return { b: ctx.a + 1 };
23
+ })
24
+ .build();
25
+ isType.equal();
26
+ expect(r).toEqual({ a: 1, b: 2 });
27
+ });
28
+ it('provides the combined context to the next transformer', () => {
29
+ const r = context({ a: 1 })
30
+ .extend(ctx => ({ b: ctx.a + 1 }))
31
+ .extend(ctx => ({ c: ctx.a + ctx.b }))
32
+ .build();
33
+ isType.equal();
34
+ expect(r).toEqual({ a: 1, b: 2, c: 3 });
35
+ });
36
+ it('accepts extenders needing partial of current context', () => {
37
+ function foo(ctx) {
38
+ return { c: ctx.a + 2 };
39
+ }
40
+ const r = context({ a: 1, b: 2 }).extend(foo).build();
41
+ isType.equal();
42
+ expect(r).toEqual({ a: 1, b: 2, c: 3 });
43
+ });
44
+ });
45
+ //# sourceMappingURL=context.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.spec.js","sourceRoot":"","sources":["../../ts/functional/context.spec.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  export type { ChainFn, EndoFn } from './ChainFn.js';
2
2
  export * from './compose.js';
3
+ export * from './context.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ts/functional/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACnD,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ts/functional/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACnD,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA"}
@@ -1,2 +1,3 @@
1
1
  export * from './compose.js';
2
+ export * from './context.js';
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/functional/index.ts"],"names":[],"mappings":"AAEA,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/functional/index.ts"],"names":[],"mappings":"AAEA,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA"}
@@ -10,6 +10,6 @@ export declare function isType<T>(subject: unknown, validator: (s: T) => unknown
10
10
  export declare namespace isType {
11
11
  var t: <T extends true>(subject?: T | undefined) => boolean;
12
12
  var f: <T extends false>(subject?: T | undefined) => boolean;
13
- var equal: <C extends Equal<A, B>, A, B>() => void;
13
+ var equal: <C extends Equal<A, B, true, false>, A, B>() => void;
14
14
  }
15
15
  //# sourceMappingURL=isType.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-plus",
3
- "version": "5.3.0",
3
+ "version": "5.4.1",
4
4
  "description": "Provides additional types for TypeScript.",
5
5
  "homepage": "https://github.com/unional/type-plus",
6
6
  "bugs": {
@@ -67,7 +67,7 @@
67
67
  "tslib": "^2.4.0",
68
68
  "typedoc": "^0.23.0",
69
69
  "typedoc-plugin-extras": "^2.2.3",
70
- "typescript": "5.0.0-dev.20230116"
70
+ "typescript": "^4.9.4"
71
71
  },
72
72
  "packageManager": "pnpm@7.25.0",
73
73
  "size-limit": [
@@ -0,0 +1,69 @@
1
+ import type { LeftJoin } from '../object/index.js'
2
+
3
+ export type ContextBaseShape = Record<string | symbol, any>
4
+
5
+ /**
6
+ * Extends the context with new props.
7
+ * @param context the current context.
8
+ * @return an additional context with new properties.
9
+ */
10
+ export type ContextExtender<
11
+ Current,
12
+ Additional
13
+ > = (context: Current) => Additional
14
+
15
+ export type ContextBuilder<
16
+ Init extends ContextBaseShape,
17
+ Ctx extends ContextBaseShape
18
+ > = {
19
+ /**
20
+ * Extends the context using an extender.
21
+ * @param extender function that add new props to the context.
22
+ *
23
+ * The extender only need to return a new object with new properties.
24
+ *
25
+ * Do not need to merge the existing context with the new props.
26
+ * The builder will do that for you.
27
+ */
28
+ extend<
29
+ Current extends ContextBaseShape = Ctx,
30
+ Additional extends ContextBaseShape = ContextBaseShape
31
+ >(extender: ContextExtender<Current, Additional>)
32
+ : ContextBuilder<Init, LeftJoin<Ctx, Additional>>,
33
+ /**
34
+ * Build and return the context.
35
+ */
36
+ build(): Ctx
37
+ }
38
+
39
+ /**
40
+ * A fluent context builder.
41
+ *
42
+ * The initializer and transformer
43
+ *
44
+ * @param init The initial context or an context initializer.
45
+ * @return the context builder where you can
46
+ * use `extend()` to add context, and
47
+ * use `build()` to build the context.
48
+ */
49
+ export function context<
50
+ Init extends ContextBaseShape,
51
+ Ctx extends ContextBaseShape = Init
52
+ >(init?: Init | (() => Init)): ContextBuilder<Init, Ctx> {
53
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
54
+ return typeof init === 'function'
55
+ ? contextBuilder({}, [init])
56
+ : contextBuilder(init ?? {}, []) as any
57
+ }
58
+
59
+ function contextBuilder(init: ContextBaseShape, transformers: ContextExtender<any, any>[]) {
60
+ return {
61
+ extend(transformer: ContextExtender<any, any>) {
62
+ return contextBuilder(init, transformers.concat(transformer))
63
+ },
64
+ build() {
65
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
66
+ return transformers.reduce((p, t) => ({ ...p, ...t(p) }), init)
67
+ }
68
+ }
69
+ }
@@ -1,3 +1,4 @@
1
1
  // export * from './Maybe.js'
2
2
  export type { ChainFn, EndoFn } from './ChainFn.js'
3
3
  export * from './compose.js'
4
+ export * from './context.js'