inferred-types 0.27.0 → 0.28.2
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/.vscode/settings.json +4 -0
- package/dist/index.d.ts +363 -165
- package/dist/index.js +64 -24
- package/dist/index.mjs +60 -23
- package/package.json +1 -1
- package/src/types/Mutable.ts +3 -1
- package/src/types/TypeInfo/Extends.ts +14 -0
- package/src/types/TypeInfo/IsBooleanLiteral.ts +9 -0
- package/src/types/TypeInfo/IsLiteral.ts +36 -2
- package/src/types/TypeInfo/IsNumericLiteral.ts +9 -0
- package/src/types/TypeInfo/IsObject.ts +27 -0
- package/src/types/TypeInfo/IsScalar.ts +14 -0
- package/src/types/TypeInfo/IsStringLiteral.ts +9 -0
- package/src/types/TypeInfo/IsUndefined.ts +14 -0
- package/src/types/TypeInfo/TypeDefault.ts +58 -0
- package/src/types/TypeInfo/index.ts +4 -0
- package/src/types/dictionary/MapTo.ts +247 -36
- package/src/types/dictionary/props.ts +11 -0
- package/src/types/kv/DictFromKv.ts +1 -1
- package/src/types/type-testing.ts +2 -5
- package/src/utility/dictionary/kv/kvToDict.ts +1 -2
- package/src/utility/dictionary/mapTo.ts +122 -77
- package/src/utility/dictionary/merge.ts +36 -0
- package/src/utility/runtime/conditions/isObject.ts +2 -16
- package/tests/TypeInfo/IsLiteral.spec.ts +17 -1
- package/tests/dictionary/IntersectingKeys.test.ts +42 -0
- package/tests/dictionary/TypeDefault.test.ts +76 -0
- package/tests/dictionary/mapTo.test.ts +214 -48
- package/tests/dictionary/merge.test.ts +41 -0
- package/tests/withValue.spec.ts +0 -1
package/dist/index.js
CHANGED
|
@@ -21,9 +21,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
Configurator: () => Configurator,
|
|
24
|
+
DEFAULT_MANY_TO_ONE_MAPPING: () => DEFAULT_MANY_TO_ONE_MAPPING,
|
|
25
|
+
DEFAULT_ONE_TO_MANY_MAPPING: () => DEFAULT_ONE_TO_MANY_MAPPING,
|
|
26
|
+
DEFAULT_ONE_TO_ONE_MAPPING: () => DEFAULT_ONE_TO_ONE_MAPPING,
|
|
24
27
|
ExplicitFunction: () => ExplicitFunction,
|
|
25
28
|
FluentConfigurator: () => FluentConfigurator,
|
|
26
|
-
|
|
29
|
+
MapCardinality: () => MapCardinality,
|
|
27
30
|
Model: () => Model,
|
|
28
31
|
MutationIdentity: () => MutationIdentity,
|
|
29
32
|
and: () => and,
|
|
@@ -130,12 +133,12 @@ var valueTypes = {
|
|
|
130
133
|
};
|
|
131
134
|
|
|
132
135
|
// src/types/dictionary/MapTo.ts
|
|
133
|
-
var
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return
|
|
138
|
-
})(
|
|
136
|
+
var MapCardinality = /* @__PURE__ */ ((MapCardinality2) => {
|
|
137
|
+
MapCardinality2["OneToMany"] = "I -> O[]";
|
|
138
|
+
MapCardinality2["OneToOne"] = "I -> O";
|
|
139
|
+
MapCardinality2["ManyToOne"] = "I[] -> O";
|
|
140
|
+
return MapCardinality2;
|
|
141
|
+
})(MapCardinality || {});
|
|
139
142
|
|
|
140
143
|
// src/utility/keys.ts
|
|
141
144
|
function keys(obj, ...without) {
|
|
@@ -590,32 +593,66 @@ function mapValues(obj, valueMapper) {
|
|
|
590
593
|
}
|
|
591
594
|
|
|
592
595
|
// src/utility/dictionary/mapTo.ts
|
|
593
|
-
var
|
|
594
|
-
config
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
596
|
+
var toFinalizedConfig = (config) => {
|
|
597
|
+
return { ...config, finalized: true };
|
|
598
|
+
};
|
|
599
|
+
var DEFAULT_ONE_TO_MANY_MAPPING = toFinalizedConfig({
|
|
600
|
+
input: "req",
|
|
601
|
+
output: "opt",
|
|
602
|
+
cardinality: "I -> O[]"
|
|
603
|
+
});
|
|
604
|
+
var DEFAULT_ONE_TO_ONE_MAPPING = toFinalizedConfig({
|
|
605
|
+
input: "req",
|
|
606
|
+
output: "req",
|
|
607
|
+
cardinality: "I -> O"
|
|
608
|
+
});
|
|
609
|
+
var DEFAULT_MANY_TO_ONE_MAPPING = toFinalizedConfig({
|
|
610
|
+
input: "req",
|
|
611
|
+
output: "req",
|
|
612
|
+
cardinality: "I[] -> O"
|
|
613
|
+
});
|
|
614
|
+
var mapper = (config) => (map) => {
|
|
615
|
+
return (source) => {
|
|
616
|
+
const isArray2 = config.cardinality === "I -> O[]" && Array.isArray(source) ? true : config.cardinality === "I[] -> O" && Array.isArray(source) && Array.isArray(source[0]) ? true : false;
|
|
602
617
|
if (isArray2) {
|
|
603
618
|
return source.flatMap(map);
|
|
604
619
|
} else {
|
|
605
620
|
return map(source);
|
|
606
621
|
}
|
|
607
622
|
};
|
|
608
|
-
return fn;
|
|
609
623
|
};
|
|
624
|
+
var setMapper = (config = { input: void 0, output: void 0, cardinality: void 0 }, defaultValue) => ({
|
|
625
|
+
map: (source) => {
|
|
626
|
+
const c = {
|
|
627
|
+
...defaultValue,
|
|
628
|
+
...config
|
|
629
|
+
};
|
|
630
|
+
return mapper(c)(source);
|
|
631
|
+
},
|
|
632
|
+
input: (config == null ? void 0 : config.input) || defaultValue.input,
|
|
633
|
+
output: (config == null ? void 0 : config.output) || defaultValue.output,
|
|
634
|
+
cardinality: (config == null ? void 0 : config.cardinality) || defaultValue.cardinality
|
|
635
|
+
});
|
|
610
636
|
var mapToFn = (map) => {
|
|
611
|
-
return mapper()(map);
|
|
637
|
+
return mapper(DEFAULT_ONE_TO_MANY_MAPPING)(map);
|
|
612
638
|
};
|
|
613
639
|
var mapToDict = {
|
|
614
|
-
config
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
640
|
+
config(config) {
|
|
641
|
+
const c = { ...DEFAULT_ONE_TO_MANY_MAPPING, ...config };
|
|
642
|
+
return setMapper(c, DEFAULT_ONE_TO_MANY_MAPPING);
|
|
643
|
+
},
|
|
644
|
+
oneToOne(config) {
|
|
645
|
+
const c = { ...DEFAULT_ONE_TO_ONE_MAPPING, ...config };
|
|
646
|
+
return setMapper(c, DEFAULT_ONE_TO_ONE_MAPPING);
|
|
647
|
+
},
|
|
648
|
+
manyToOne(config) {
|
|
649
|
+
const c = { ...DEFAULT_MANY_TO_ONE_MAPPING, ...config };
|
|
650
|
+
return setMapper(c, DEFAULT_MANY_TO_ONE_MAPPING);
|
|
651
|
+
},
|
|
652
|
+
oneToMany(config) {
|
|
653
|
+
const c = { ...DEFAULT_ONE_TO_MANY_MAPPING, ...config };
|
|
654
|
+
return setMapper(c, DEFAULT_ONE_TO_MANY_MAPPING);
|
|
655
|
+
}
|
|
619
656
|
};
|
|
620
657
|
var mapTo = createFnWithProps(mapToFn, mapToDict);
|
|
621
658
|
|
|
@@ -783,9 +820,12 @@ function Model(name) {
|
|
|
783
820
|
// Annotate the CommonJS export names for ESM import in node:
|
|
784
821
|
0 && (module.exports = {
|
|
785
822
|
Configurator,
|
|
823
|
+
DEFAULT_MANY_TO_ONE_MAPPING,
|
|
824
|
+
DEFAULT_ONE_TO_MANY_MAPPING,
|
|
825
|
+
DEFAULT_ONE_TO_ONE_MAPPING,
|
|
786
826
|
ExplicitFunction,
|
|
787
827
|
FluentConfigurator,
|
|
788
|
-
|
|
828
|
+
MapCardinality,
|
|
789
829
|
Model,
|
|
790
830
|
MutationIdentity,
|
|
791
831
|
and,
|
package/dist/index.mjs
CHANGED
|
@@ -42,12 +42,12 @@ var valueTypes = {
|
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
// src/types/dictionary/MapTo.ts
|
|
45
|
-
var
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return
|
|
50
|
-
})(
|
|
45
|
+
var MapCardinality = /* @__PURE__ */ ((MapCardinality2) => {
|
|
46
|
+
MapCardinality2["OneToMany"] = "I -> O[]";
|
|
47
|
+
MapCardinality2["OneToOne"] = "I -> O";
|
|
48
|
+
MapCardinality2["ManyToOne"] = "I[] -> O";
|
|
49
|
+
return MapCardinality2;
|
|
50
|
+
})(MapCardinality || {});
|
|
51
51
|
|
|
52
52
|
// src/utility/keys.ts
|
|
53
53
|
function keys(obj, ...without) {
|
|
@@ -502,32 +502,66 @@ function mapValues(obj, valueMapper) {
|
|
|
502
502
|
}
|
|
503
503
|
|
|
504
504
|
// src/utility/dictionary/mapTo.ts
|
|
505
|
-
var
|
|
506
|
-
config
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
505
|
+
var toFinalizedConfig = (config) => {
|
|
506
|
+
return { ...config, finalized: true };
|
|
507
|
+
};
|
|
508
|
+
var DEFAULT_ONE_TO_MANY_MAPPING = toFinalizedConfig({
|
|
509
|
+
input: "req",
|
|
510
|
+
output: "opt",
|
|
511
|
+
cardinality: "I -> O[]"
|
|
512
|
+
});
|
|
513
|
+
var DEFAULT_ONE_TO_ONE_MAPPING = toFinalizedConfig({
|
|
514
|
+
input: "req",
|
|
515
|
+
output: "req",
|
|
516
|
+
cardinality: "I -> O"
|
|
517
|
+
});
|
|
518
|
+
var DEFAULT_MANY_TO_ONE_MAPPING = toFinalizedConfig({
|
|
519
|
+
input: "req",
|
|
520
|
+
output: "req",
|
|
521
|
+
cardinality: "I[] -> O"
|
|
522
|
+
});
|
|
523
|
+
var mapper = (config) => (map) => {
|
|
524
|
+
return (source) => {
|
|
525
|
+
const isArray2 = config.cardinality === "I -> O[]" && Array.isArray(source) ? true : config.cardinality === "I[] -> O" && Array.isArray(source) && Array.isArray(source[0]) ? true : false;
|
|
514
526
|
if (isArray2) {
|
|
515
527
|
return source.flatMap(map);
|
|
516
528
|
} else {
|
|
517
529
|
return map(source);
|
|
518
530
|
}
|
|
519
531
|
};
|
|
520
|
-
return fn;
|
|
521
532
|
};
|
|
533
|
+
var setMapper = (config = { input: void 0, output: void 0, cardinality: void 0 }, defaultValue) => ({
|
|
534
|
+
map: (source) => {
|
|
535
|
+
const c = {
|
|
536
|
+
...defaultValue,
|
|
537
|
+
...config
|
|
538
|
+
};
|
|
539
|
+
return mapper(c)(source);
|
|
540
|
+
},
|
|
541
|
+
input: (config == null ? void 0 : config.input) || defaultValue.input,
|
|
542
|
+
output: (config == null ? void 0 : config.output) || defaultValue.output,
|
|
543
|
+
cardinality: (config == null ? void 0 : config.cardinality) || defaultValue.cardinality
|
|
544
|
+
});
|
|
522
545
|
var mapToFn = (map) => {
|
|
523
|
-
return mapper()(map);
|
|
546
|
+
return mapper(DEFAULT_ONE_TO_MANY_MAPPING)(map);
|
|
524
547
|
};
|
|
525
548
|
var mapToDict = {
|
|
526
|
-
config
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
549
|
+
config(config) {
|
|
550
|
+
const c = { ...DEFAULT_ONE_TO_MANY_MAPPING, ...config };
|
|
551
|
+
return setMapper(c, DEFAULT_ONE_TO_MANY_MAPPING);
|
|
552
|
+
},
|
|
553
|
+
oneToOne(config) {
|
|
554
|
+
const c = { ...DEFAULT_ONE_TO_ONE_MAPPING, ...config };
|
|
555
|
+
return setMapper(c, DEFAULT_ONE_TO_ONE_MAPPING);
|
|
556
|
+
},
|
|
557
|
+
manyToOne(config) {
|
|
558
|
+
const c = { ...DEFAULT_MANY_TO_ONE_MAPPING, ...config };
|
|
559
|
+
return setMapper(c, DEFAULT_MANY_TO_ONE_MAPPING);
|
|
560
|
+
},
|
|
561
|
+
oneToMany(config) {
|
|
562
|
+
const c = { ...DEFAULT_ONE_TO_MANY_MAPPING, ...config };
|
|
563
|
+
return setMapper(c, DEFAULT_ONE_TO_MANY_MAPPING);
|
|
564
|
+
}
|
|
531
565
|
};
|
|
532
566
|
var mapTo = createFnWithProps(mapToFn, mapToDict);
|
|
533
567
|
|
|
@@ -694,9 +728,12 @@ function Model(name) {
|
|
|
694
728
|
}
|
|
695
729
|
export {
|
|
696
730
|
Configurator,
|
|
731
|
+
DEFAULT_MANY_TO_ONE_MAPPING,
|
|
732
|
+
DEFAULT_ONE_TO_MANY_MAPPING,
|
|
733
|
+
DEFAULT_ONE_TO_ONE_MAPPING,
|
|
697
734
|
ExplicitFunction,
|
|
698
735
|
FluentConfigurator,
|
|
699
|
-
|
|
736
|
+
MapCardinality,
|
|
700
737
|
Model,
|
|
701
738
|
MutationIdentity,
|
|
702
739
|
and,
|
package/package.json
CHANGED
package/src/types/Mutable.ts
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **Extends**
|
|
3
|
+
*
|
|
4
|
+
* Boolean type utility which returns `true` if `E` _extends_ `T`.
|
|
5
|
+
*/
|
|
6
|
+
export type Extends<E, T> = E extends T ? true : false;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* **IfExtends**
|
|
10
|
+
*
|
|
11
|
+
* Branching type utility which returns type `IF` when `E` _extends_ `T`; otherwise
|
|
12
|
+
* it will return the type `ELSE`.
|
|
13
|
+
*/
|
|
14
|
+
export type IfExtends<E, T, IF, ELSE> = Extends<E, T> extends true ? IF : ELSE;
|
|
@@ -5,3 +5,12 @@
|
|
|
5
5
|
* just the wider _boolean_ type.
|
|
6
6
|
*/
|
|
7
7
|
export type IsBooleanLiteral<T extends boolean> = boolean extends T ? false : true;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* **IfBooleanLiteral**
|
|
11
|
+
*
|
|
12
|
+
* Branch utility which returns `IF` type when `T` is a boolean literal and `ELSE` otherwise
|
|
13
|
+
*/
|
|
14
|
+
export type IfBooleanLiteral<T extends boolean, IF, ELSE> = IsBooleanLiteral<T> extends true
|
|
15
|
+
? IF
|
|
16
|
+
: ELSE;
|
|
@@ -11,10 +11,44 @@ import { IsNumericLiteral } from "./IsNumericLiteral";
|
|
|
11
11
|
* string, number, or boolean -- is a _literal_ value of that type (true) or
|
|
12
12
|
* the more generic wide type (false).
|
|
13
13
|
*/
|
|
14
|
-
export type IsLiteral<T
|
|
14
|
+
export type IsLiteral<T> = [T] extends [string]
|
|
15
15
|
? IsStringLiteral<T>
|
|
16
16
|
: [T] extends [boolean]
|
|
17
17
|
? IsBooleanLiteral<T>
|
|
18
18
|
: [T] extends [number]
|
|
19
19
|
? IsNumericLiteral<T>
|
|
20
|
-
:
|
|
20
|
+
: false;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* **IsOptionalLiteral**
|
|
24
|
+
*
|
|
25
|
+
* Type utility which returns true/false if the value passed -- a form of a
|
|
26
|
+
* string, number, or boolean -- is a _literal_ value of that type (true) or
|
|
27
|
+
* the more generic wide type (false).
|
|
28
|
+
*
|
|
29
|
+
* This type also strips off _undefined_ from any possible union type to evaluate
|
|
30
|
+
* to `true` even when a literal value is in union with _undefined_. If you don't
|
|
31
|
+
* want to test for the union with _undefined_ use the `IsOptional` utility instead.
|
|
32
|
+
*/
|
|
33
|
+
export type IsOptionalLiteral<T> = [Exclude<T, undefined>] extends [string]
|
|
34
|
+
? IsStringLiteral<Exclude<T, undefined>>
|
|
35
|
+
: [Exclude<T, undefined>] extends [boolean]
|
|
36
|
+
? IsBooleanLiteral<Exclude<T, undefined>>
|
|
37
|
+
: [Exclude<T, undefined>] extends [number]
|
|
38
|
+
? IsNumericLiteral<Exclude<T, undefined>>
|
|
39
|
+
: false;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* **IfLiteral**
|
|
43
|
+
*
|
|
44
|
+
* Branch type utility with return `IF` when `T` is a _literal_ value and `ELSE` otherwise
|
|
45
|
+
*/
|
|
46
|
+
export type IfLiteral<T, IF, ELSE> = IsLiteral<T> extends true ? IF : ELSE;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* **IfOptionalLiteral**
|
|
50
|
+
*
|
|
51
|
+
* Branch type utility with return `IF` when `T` is a _literal_ value (with possibly
|
|
52
|
+
* the inclusion of _undefined_); otherwise returns the type `ELSE`
|
|
53
|
+
*/
|
|
54
|
+
export type IfOptionalLiteral<T, IF, ELSE> = IsOptionalLiteral<T> extends true ? IF : ELSE;
|
|
@@ -5,3 +5,12 @@
|
|
|
5
5
|
* just the _number_ type.
|
|
6
6
|
*/
|
|
7
7
|
export type IsNumericLiteral<T extends number> = number extends T ? false : true;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* **IfNumericLiteral**
|
|
11
|
+
*
|
|
12
|
+
* Branch utility which returns `IF` type when `T` is a numeric literal and `ELSE` otherwise
|
|
13
|
+
*/
|
|
14
|
+
export type IfNumericLiteral<T extends number, IF, ELSE> = IsNumericLiteral<T> extends true
|
|
15
|
+
? IF
|
|
16
|
+
: ELSE;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { FunctionType } from "../FunctionType";
|
|
2
|
+
import { Mutable } from "../Mutable";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* **IsObject**
|
|
6
|
+
*
|
|
7
|
+
* Boolean type utility used to check whether a type `T` is an object
|
|
8
|
+
*/
|
|
9
|
+
export type IsObject<T> = Mutable<T> extends Record<string, any>
|
|
10
|
+
? // an object of some type
|
|
11
|
+
T extends FunctionType
|
|
12
|
+
? // when a function with props is found, categorize as a function not object
|
|
13
|
+
false
|
|
14
|
+
: Mutable<T> extends any[]
|
|
15
|
+
? // Array's are objects too but in our narrower definition we're looking only
|
|
16
|
+
// dictionary based arrays.
|
|
17
|
+
false
|
|
18
|
+
: true
|
|
19
|
+
: false;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* **IfObject**
|
|
23
|
+
*
|
|
24
|
+
* Branch type utility with return `IF` when `T` extends an object type
|
|
25
|
+
* and `ELSE` otherwise
|
|
26
|
+
*/
|
|
27
|
+
export type IfObject<T, IF, ELSE> = IsObject<T> extends true ? IF : ELSE;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type IsScalar<T> = [T] extends [string]
|
|
2
|
+
? true
|
|
3
|
+
: [T] extends [number]
|
|
4
|
+
? true
|
|
5
|
+
: [T] extends [boolean]
|
|
6
|
+
? true
|
|
7
|
+
: false;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* **IfScalar**
|
|
11
|
+
*
|
|
12
|
+
* Branch type utility which returns `IF` when `T` is a scalar value and `ELSE` otherwise
|
|
13
|
+
*/
|
|
14
|
+
export type IfScalar<T, IF, ELSE> = IsScalar<T> extends true ? IF : ELSE;
|
|
@@ -5,3 +5,12 @@
|
|
|
5
5
|
* just the _string_ type.
|
|
6
6
|
*/
|
|
7
7
|
export type IsStringLiteral<T extends string> = string extends T ? false : true;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* **IfStringLiteral**
|
|
11
|
+
*
|
|
12
|
+
* Branch utility which returns `IF` type when `T` is a string literal and `ELSE` otherwise
|
|
13
|
+
*/
|
|
14
|
+
export type IfStringLiteral<T extends string, IF, ELSE> = IsStringLiteral<T> extends true
|
|
15
|
+
? IF
|
|
16
|
+
: ELSE;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **IsUndefined**
|
|
3
|
+
*
|
|
4
|
+
* Boolean type utility returns `true` if `T` is undefined; `false` otherwise
|
|
5
|
+
*/
|
|
6
|
+
export type IsUndefined<T> = T extends undefined ? true : false;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* **IfUndefined**
|
|
10
|
+
*
|
|
11
|
+
* Branch utility which returns `IF` type when `T` is an _undefined_ value
|
|
12
|
+
* otherwise returns `ELSE` type
|
|
13
|
+
*/
|
|
14
|
+
export type IfUndefined<T, IF, ELSE> = IsUndefined<T> extends true ? IF : ELSE;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { IsObject } from "src/types/TypeInfo";
|
|
2
|
+
import { SimplifyObject } from "../SimplifyObject";
|
|
3
|
+
import { IfExtends } from "./Extends";
|
|
4
|
+
import { IfOptionalLiteral } from "./IsLiteral";
|
|
5
|
+
import { IfUndefined } from "./IsUndefined";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* **TypeDefault**
|
|
9
|
+
*
|
|
10
|
+
* A type utility designed to help maintain strong and narrow types where
|
|
11
|
+
* you have a value `T` which _might_ be **undefined** and a type `D` which
|
|
12
|
+
* defines all the _default_ type for `T`.
|
|
13
|
+
*
|
|
14
|
+
* - In all cases we compare first whether `T` is undefined and replace it's
|
|
15
|
+
* type with `D` 1-for-1 if it is
|
|
16
|
+
* - To address a larger set of use cases, when `D` _extends_ an object we will
|
|
17
|
+
* compare each property of `D` against `T`
|
|
18
|
+
* ```ts
|
|
19
|
+
* type I = { foo?: "foo" | undefined; bar?: 42 | 53 | undefined };
|
|
20
|
+
* type D = { foo: "foo"; bar: 53 };
|
|
21
|
+
* type DF = TypeDefault<I,D>; // `D`
|
|
22
|
+
* const i = { foo: undefined, bar: 99 } as const;
|
|
23
|
+
* type DF2 = TypeDefault<typeof i, D>; // `{ foo: "foo"; bar: 99 }`
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export type TypeDefault<T, D> = //
|
|
27
|
+
IsObject<D> extends true //
|
|
28
|
+
? IsObject<T> extends true
|
|
29
|
+
? // both T and D are objects; start by iterating over D
|
|
30
|
+
SimplifyObject<{
|
|
31
|
+
[K in keyof D]: K extends keyof T
|
|
32
|
+
? // both D[T] and K[T] are present
|
|
33
|
+
TypeDefault<T[K], D[K]>
|
|
34
|
+
: // only D[K] present
|
|
35
|
+
D[K];
|
|
36
|
+
}>
|
|
37
|
+
: // T is not an object, but D is
|
|
38
|
+
IfUndefined<
|
|
39
|
+
T, // check if T is undefined
|
|
40
|
+
D, // use D as the type
|
|
41
|
+
Exclude<T, undefined> // use T as the type but remove "undefined"
|
|
42
|
+
>
|
|
43
|
+
: // neither D or T is an object
|
|
44
|
+
IfUndefined<
|
|
45
|
+
T, // check whether is T is undefined
|
|
46
|
+
D, // assign to D if it is
|
|
47
|
+
IfOptionalLiteral<
|
|
48
|
+
T, // if T is a literal
|
|
49
|
+
IfExtends<
|
|
50
|
+
D,
|
|
51
|
+
T,
|
|
52
|
+
D, // use D since it extends the value of T
|
|
53
|
+
Exclude<T, undefined> // use T's literal value minus "undefined"
|
|
54
|
+
>,
|
|
55
|
+
// T is a wide type
|
|
56
|
+
Exclude<T, undefined>
|
|
57
|
+
>
|
|
58
|
+
>;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export * from "./Includes";
|
|
2
2
|
export * from "./IsBooleanLiteral";
|
|
3
3
|
export * from "./IsNumericLiteral";
|
|
4
|
+
export * from "./IsScalar";
|
|
4
5
|
export * from "./IsStringLiteral";
|
|
5
6
|
export * from "./IsLiteral";
|
|
7
|
+
export * from "./Extends";
|
|
8
|
+
export * from "./TypeDefault";
|
|
9
|
+
export * from "./IsObject";
|