type-plus 4.12.1 → 4.13.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 +2 -0
- package/cjs/utils/index.d.ts +37 -0
- package/cjs/utils/index.d.ts.map +1 -1
- package/cjs/utils/index.spec.d.ts +2 -0
- package/cjs/utils/index.spec.d.ts.map +1 -0
- package/cjs/utils/index.spec.js +81 -0
- package/cjs/utils/index.spec.js.map +1 -0
- package/esm/utils/index.d.ts +37 -0
- package/esm/utils/index.d.ts.map +1 -1
- package/esm/utils/index.spec.d.ts +2 -0
- package/esm/utils/index.spec.d.ts.map +1 -0
- package/esm/utils/index.spec.js +79 -0
- package/esm/utils/index.spec.js.map +1 -0
- package/package.json +1 -1
- package/ts/utils/index.ts +47 -0
package/README.md
CHANGED
|
@@ -380,6 +380,8 @@ JSONTypes.get<string>(someJson, 'a', 'b', 1, 'c') // miku
|
|
|
380
380
|
- `BNotA<A, B>`: flip of `ANotB`
|
|
381
381
|
- `as<T>(subject)`: assert `subject` as `T`. Avoid ASI issues such as `;(x as T).abc`
|
|
382
382
|
- `asAny(subject)`: assert `subject` as `any`. Avoid ASI issue such as `;(x as any).abc`
|
|
383
|
+
- `EitherAnd<A, B, [C, D]>`: combines 2 to 4 types as `A | B | (A & B)`. This is useful for combining options. **Deprecated**. Renamed to `EitherOrBoth`.
|
|
384
|
+
- `EitherOrBoth<A, B, [C, D]>`: combines 2 to 4 types as `A | B | (A & B)`. This is useful for combining options.
|
|
383
385
|
- `Except<T, K>`: Deprecated. Same as `Omit<T, K>`.
|
|
384
386
|
- `ExcludePropType<T, U>`: excludes type `U` from properties in `T`.
|
|
385
387
|
- `KeyofOptional<T>`: `keyof` that works with `Record<any, any> | undefined`.
|
package/cjs/utils/index.d.ts
CHANGED
|
@@ -2,4 +2,41 @@ export * from './as.js';
|
|
|
2
2
|
export type { NonNull } from './NonNull.js';
|
|
3
3
|
export type { NonUndefined } from './NonUndefined.js';
|
|
4
4
|
export type { Widen } from './Widen.js';
|
|
5
|
+
/**
|
|
6
|
+
* `A` | `B` | `A & B`.
|
|
7
|
+
* Supports up to 4 types, and it is composable.
|
|
8
|
+
* This is useful when you want to compose multiple options together,
|
|
9
|
+
* while preserving their required field and structure.
|
|
10
|
+
* If the types overlaps each other, you may run into some corner cases.
|
|
11
|
+
* But in general usage it should work as expected.
|
|
12
|
+
* @example
|
|
13
|
+
* type A = { src: string, minify?: boolean }
|
|
14
|
+
* type B = { logLevel: number }
|
|
15
|
+
* function config(options: EitherAnd<A, B>) { }
|
|
16
|
+
*
|
|
17
|
+
* config({ logLevel: 1 })
|
|
18
|
+
* config({ src: 'src' })
|
|
19
|
+
* config({ src: 'src', minify: false })
|
|
20
|
+
* config({ minify: false }) // INVALID
|
|
21
|
+
*/
|
|
22
|
+
export declare type EitherOrBoth<A, B, C = void, D = void> = C extends void ? A | B | A & B : (D extends void ? A | B | C | A & B | A & C | B & C | A & B & C : A | B | C | D | A & B | A & C | A & D | B & C | B & D | C & D | A & B & C | A & B & D | A & C & D | B & C & D | A & B & C & D);
|
|
23
|
+
/**
|
|
24
|
+
* `A` | `B` | `A & B`.
|
|
25
|
+
* Supports up to 4 types, and it is composable.
|
|
26
|
+
* This is useful when you want to compose multiple options together,
|
|
27
|
+
* while preserving their required field and structure.
|
|
28
|
+
* If the types overlaps each other, you may run into some corner cases.
|
|
29
|
+
* But in general usage it should work as expected.
|
|
30
|
+
* @deprecated renamed to `EitherOrBoth`
|
|
31
|
+
* @example
|
|
32
|
+
* type A = { src: string, minify?: boolean }
|
|
33
|
+
* type B = { logLevel: number }
|
|
34
|
+
* function config(options: EitherAnd<A, B>) { }
|
|
35
|
+
*
|
|
36
|
+
* config({ logLevel: 1 })
|
|
37
|
+
* config({ src: 'src' })
|
|
38
|
+
* config({ src: 'src', minify: false })
|
|
39
|
+
* config({ minify: false }) // INVALID
|
|
40
|
+
*/
|
|
41
|
+
export declare type EitherAnd<A, B, C = void, D = void> = EitherOrBoth<A, B, C, D>;
|
|
5
42
|
//# sourceMappingURL=index.d.ts.map
|
package/cjs/utils/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ts/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ts/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEvC;;;;;;;;;;;;;;;;GAgBG;AACH,oBAAY,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,IAAI,CAAC,SAAS,IAAI,GAC/D,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GACb,CAAC,CAAC,SAAS,IAAI,GACb,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAC7C,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GACf,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAC7C,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAC7C,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CACd,CAAA;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACF,oBAAY,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.spec.d.ts","sourceRoot":"","sources":["../../ts/utils/index.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var index_js_1 = require("../index.js");
|
|
4
|
+
describe('Either<A, B>', function () {
|
|
5
|
+
it('allows just A', function () {
|
|
6
|
+
index_js_1.isType.equal();
|
|
7
|
+
index_js_1.isType.equal();
|
|
8
|
+
index_js_1.isType.equal();
|
|
9
|
+
index_js_1.isType.equal();
|
|
10
|
+
});
|
|
11
|
+
it('allows just B', function () {
|
|
12
|
+
index_js_1.isType.equal();
|
|
13
|
+
index_js_1.isType.equal();
|
|
14
|
+
index_js_1.isType.equal();
|
|
15
|
+
index_js_1.isType.equal();
|
|
16
|
+
});
|
|
17
|
+
it('allows A & B', function () {
|
|
18
|
+
index_js_1.isType.equal();
|
|
19
|
+
index_js_1.isType.equal();
|
|
20
|
+
index_js_1.isType.equal();
|
|
21
|
+
index_js_1.isType.equal();
|
|
22
|
+
index_js_1.isType.equal();
|
|
23
|
+
index_js_1.isType.equal();
|
|
24
|
+
index_js_1.isType.equal();
|
|
25
|
+
index_js_1.isType.equal();
|
|
26
|
+
});
|
|
27
|
+
it('can use isType() to type guard the value', function () {
|
|
28
|
+
function foo(o) {
|
|
29
|
+
if ((0, index_js_1.isType)(o, function (o) { return typeof o.a === 'number'; })) {
|
|
30
|
+
index_js_1.isType.equal();
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
throw new Error('should not reach');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
foo({ a: 1 });
|
|
37
|
+
});
|
|
38
|
+
it('will make sure required field to be filled in when specifying optional field', function () {
|
|
39
|
+
index_js_1.isType.equal();
|
|
40
|
+
index_js_1.isType.equal();
|
|
41
|
+
});
|
|
42
|
+
it('allows A, B, C', function () {
|
|
43
|
+
index_js_1.isType.equal();
|
|
44
|
+
index_js_1.isType.equal();
|
|
45
|
+
index_js_1.isType.equal();
|
|
46
|
+
index_js_1.isType.equal();
|
|
47
|
+
index_js_1.isType.equal();
|
|
48
|
+
index_js_1.isType.equal();
|
|
49
|
+
index_js_1.isType.equal();
|
|
50
|
+
index_js_1.isType.equal();
|
|
51
|
+
});
|
|
52
|
+
it('allows A, B, C, D', function () {
|
|
53
|
+
index_js_1.isType.equal();
|
|
54
|
+
index_js_1.isType.equal();
|
|
55
|
+
index_js_1.isType.equal();
|
|
56
|
+
index_js_1.isType.equal();
|
|
57
|
+
index_js_1.isType.equal();
|
|
58
|
+
index_js_1.isType.equal();
|
|
59
|
+
index_js_1.isType.equal();
|
|
60
|
+
index_js_1.isType.equal();
|
|
61
|
+
index_js_1.isType.equal();
|
|
62
|
+
index_js_1.isType.equal();
|
|
63
|
+
index_js_1.isType.equal();
|
|
64
|
+
index_js_1.isType.equal();
|
|
65
|
+
index_js_1.isType.equal();
|
|
66
|
+
index_js_1.isType.equal();
|
|
67
|
+
index_js_1.isType.equal();
|
|
68
|
+
index_js_1.isType.equal();
|
|
69
|
+
index_js_1.isType.equal();
|
|
70
|
+
index_js_1.isType.equal();
|
|
71
|
+
index_js_1.isType.equal();
|
|
72
|
+
});
|
|
73
|
+
it('can compose', function () {
|
|
74
|
+
index_js_1.isType.equal();
|
|
75
|
+
index_js_1.isType.equal();
|
|
76
|
+
index_js_1.isType.equal();
|
|
77
|
+
index_js_1.isType.equal();
|
|
78
|
+
index_js_1.isType.equal();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=index.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.spec.js","sourceRoot":"","sources":["../../ts/utils/index.spec.ts"],"names":[],"mappings":"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"}
|
package/esm/utils/index.d.ts
CHANGED
|
@@ -2,4 +2,41 @@ export * from './as.js';
|
|
|
2
2
|
export type { NonNull } from './NonNull.js';
|
|
3
3
|
export type { NonUndefined } from './NonUndefined.js';
|
|
4
4
|
export type { Widen } from './Widen.js';
|
|
5
|
+
/**
|
|
6
|
+
* `A` | `B` | `A & B`.
|
|
7
|
+
* Supports up to 4 types, and it is composable.
|
|
8
|
+
* This is useful when you want to compose multiple options together,
|
|
9
|
+
* while preserving their required field and structure.
|
|
10
|
+
* If the types overlaps each other, you may run into some corner cases.
|
|
11
|
+
* But in general usage it should work as expected.
|
|
12
|
+
* @example
|
|
13
|
+
* type A = { src: string, minify?: boolean }
|
|
14
|
+
* type B = { logLevel: number }
|
|
15
|
+
* function config(options: EitherAnd<A, B>) { }
|
|
16
|
+
*
|
|
17
|
+
* config({ logLevel: 1 })
|
|
18
|
+
* config({ src: 'src' })
|
|
19
|
+
* config({ src: 'src', minify: false })
|
|
20
|
+
* config({ minify: false }) // INVALID
|
|
21
|
+
*/
|
|
22
|
+
export declare type EitherOrBoth<A, B, C = void, D = void> = C extends void ? A | B | A & B : (D extends void ? A | B | C | A & B | A & C | B & C | A & B & C : A | B | C | D | A & B | A & C | A & D | B & C | B & D | C & D | A & B & C | A & B & D | A & C & D | B & C & D | A & B & C & D);
|
|
23
|
+
/**
|
|
24
|
+
* `A` | `B` | `A & B`.
|
|
25
|
+
* Supports up to 4 types, and it is composable.
|
|
26
|
+
* This is useful when you want to compose multiple options together,
|
|
27
|
+
* while preserving their required field and structure.
|
|
28
|
+
* If the types overlaps each other, you may run into some corner cases.
|
|
29
|
+
* But in general usage it should work as expected.
|
|
30
|
+
* @deprecated renamed to `EitherOrBoth`
|
|
31
|
+
* @example
|
|
32
|
+
* type A = { src: string, minify?: boolean }
|
|
33
|
+
* type B = { logLevel: number }
|
|
34
|
+
* function config(options: EitherAnd<A, B>) { }
|
|
35
|
+
*
|
|
36
|
+
* config({ logLevel: 1 })
|
|
37
|
+
* config({ src: 'src' })
|
|
38
|
+
* config({ src: 'src', minify: false })
|
|
39
|
+
* config({ minify: false }) // INVALID
|
|
40
|
+
*/
|
|
41
|
+
export declare type EitherAnd<A, B, C = void, D = void> = EitherOrBoth<A, B, C, D>;
|
|
5
42
|
//# sourceMappingURL=index.d.ts.map
|
package/esm/utils/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ts/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ts/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEvC;;;;;;;;;;;;;;;;GAgBG;AACH,oBAAY,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,IAAI,CAAC,SAAS,IAAI,GAC/D,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GACb,CAAC,CAAC,SAAS,IAAI,GACb,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAC7C,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GACf,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAC7C,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAC7C,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CACd,CAAA;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACF,oBAAY,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.spec.d.ts","sourceRoot":"","sources":["../../ts/utils/index.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { isType } from '../index.js';
|
|
2
|
+
describe('Either<A, B>', () => {
|
|
3
|
+
it('allows just A', () => {
|
|
4
|
+
isType.equal();
|
|
5
|
+
isType.equal();
|
|
6
|
+
isType.equal();
|
|
7
|
+
isType.equal();
|
|
8
|
+
});
|
|
9
|
+
it('allows just B', () => {
|
|
10
|
+
isType.equal();
|
|
11
|
+
isType.equal();
|
|
12
|
+
isType.equal();
|
|
13
|
+
isType.equal();
|
|
14
|
+
});
|
|
15
|
+
it('allows A & B', () => {
|
|
16
|
+
isType.equal();
|
|
17
|
+
isType.equal();
|
|
18
|
+
isType.equal();
|
|
19
|
+
isType.equal();
|
|
20
|
+
isType.equal();
|
|
21
|
+
isType.equal();
|
|
22
|
+
isType.equal();
|
|
23
|
+
isType.equal();
|
|
24
|
+
});
|
|
25
|
+
it('can use isType() to type guard the value', () => {
|
|
26
|
+
function foo(o) {
|
|
27
|
+
if (isType(o, o => typeof o.a === 'number')) {
|
|
28
|
+
isType.equal();
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
throw new Error('should not reach');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
foo({ a: 1 });
|
|
35
|
+
});
|
|
36
|
+
it('will make sure required field to be filled in when specifying optional field', () => {
|
|
37
|
+
isType.equal();
|
|
38
|
+
isType.equal();
|
|
39
|
+
});
|
|
40
|
+
it('allows A, B, C', () => {
|
|
41
|
+
isType.equal();
|
|
42
|
+
isType.equal();
|
|
43
|
+
isType.equal();
|
|
44
|
+
isType.equal();
|
|
45
|
+
isType.equal();
|
|
46
|
+
isType.equal();
|
|
47
|
+
isType.equal();
|
|
48
|
+
isType.equal();
|
|
49
|
+
});
|
|
50
|
+
it('allows A, B, C, D', () => {
|
|
51
|
+
isType.equal();
|
|
52
|
+
isType.equal();
|
|
53
|
+
isType.equal();
|
|
54
|
+
isType.equal();
|
|
55
|
+
isType.equal();
|
|
56
|
+
isType.equal();
|
|
57
|
+
isType.equal();
|
|
58
|
+
isType.equal();
|
|
59
|
+
isType.equal();
|
|
60
|
+
isType.equal();
|
|
61
|
+
isType.equal();
|
|
62
|
+
isType.equal();
|
|
63
|
+
isType.equal();
|
|
64
|
+
isType.equal();
|
|
65
|
+
isType.equal();
|
|
66
|
+
isType.equal();
|
|
67
|
+
isType.equal();
|
|
68
|
+
isType.equal();
|
|
69
|
+
isType.equal();
|
|
70
|
+
});
|
|
71
|
+
it('can compose', () => {
|
|
72
|
+
isType.equal();
|
|
73
|
+
isType.equal();
|
|
74
|
+
isType.equal();
|
|
75
|
+
isType.equal();
|
|
76
|
+
isType.equal();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=index.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.spec.js","sourceRoot":"","sources":["../../ts/utils/index.spec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/ts/utils/index.ts
CHANGED
|
@@ -2,3 +2,50 @@ export * from './as.js'
|
|
|
2
2
|
export type { NonNull } from './NonNull.js'
|
|
3
3
|
export type { NonUndefined } from './NonUndefined.js'
|
|
4
4
|
export type { Widen } from './Widen.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `A` | `B` | `A & B`.
|
|
8
|
+
* Supports up to 4 types, and it is composable.
|
|
9
|
+
* This is useful when you want to compose multiple options together,
|
|
10
|
+
* while preserving their required field and structure.
|
|
11
|
+
* If the types overlaps each other, you may run into some corner cases.
|
|
12
|
+
* But in general usage it should work as expected.
|
|
13
|
+
* @example
|
|
14
|
+
* type A = { src: string, minify?: boolean }
|
|
15
|
+
* type B = { logLevel: number }
|
|
16
|
+
* function config(options: EitherAnd<A, B>) { }
|
|
17
|
+
*
|
|
18
|
+
* config({ logLevel: 1 })
|
|
19
|
+
* config({ src: 'src' })
|
|
20
|
+
* config({ src: 'src', minify: false })
|
|
21
|
+
* config({ minify: false }) // INVALID
|
|
22
|
+
*/
|
|
23
|
+
export type EitherOrBoth<A, B, C = void, D = void> = C extends void
|
|
24
|
+
? A | B | A & B
|
|
25
|
+
: (D extends void
|
|
26
|
+
? A | B | C | A & B | A & C | B & C | A & B & C
|
|
27
|
+
: A | B | C | D |
|
|
28
|
+
A & B | A & C | A & D | B & C | B & D | C & D |
|
|
29
|
+
A & B & C | A & B & D | A & C & D | B & C & D |
|
|
30
|
+
A & B & C & D
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* `A` | `B` | `A & B`.
|
|
35
|
+
* Supports up to 4 types, and it is composable.
|
|
36
|
+
* This is useful when you want to compose multiple options together,
|
|
37
|
+
* while preserving their required field and structure.
|
|
38
|
+
* If the types overlaps each other, you may run into some corner cases.
|
|
39
|
+
* But in general usage it should work as expected.
|
|
40
|
+
* @deprecated renamed to `EitherOrBoth`
|
|
41
|
+
* @example
|
|
42
|
+
* type A = { src: string, minify?: boolean }
|
|
43
|
+
* type B = { logLevel: number }
|
|
44
|
+
* function config(options: EitherAnd<A, B>) { }
|
|
45
|
+
*
|
|
46
|
+
* config({ logLevel: 1 })
|
|
47
|
+
* config({ src: 'src' })
|
|
48
|
+
* config({ src: 'src', minify: false })
|
|
49
|
+
* config({ minify: false }) // INVALID
|
|
50
|
+
*/
|
|
51
|
+
export type EitherAnd<A, B, C = void, D = void> = EitherOrBoth<A, B, C, D>
|