inferred-types 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +5 -0
- package/dist/index.d.ts +441 -126
- package/dist/index.js +80 -6
- package/dist/index.mjs +74 -6
- 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/alphabetic/Cardinality.ts +80 -0
- package/src/types/alphabetic/index.ts +1 -0
- package/src/types/dictionary/MapTo.ts +332 -13
- package/src/types/dictionary/props.ts +11 -0
- package/src/types/index.ts +1 -0
- package/src/types/kv/DictFromKv.ts +1 -1
- package/src/types/literal-unions/OptRequired.ts +4 -0
- package/src/types/literal-unions/index.ts +1 -0
- package/src/types/string-literals/Replace.ts +8 -4
- package/src/types/type-testing.ts +2 -5
- package/src/utility/dictionary/kv/kvToDict.ts +1 -2
- package/src/utility/dictionary/mapTo.ts +160 -28
- 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/createFnWithProps.spec.ts +1 -0
- package/tests/dictionary/IntersectingKeys.test.ts +42 -0
- package/tests/dictionary/TypeDefault.test.ts +76 -0
- package/tests/dictionary/mapTo.test.ts +327 -94
- package/tests/dictionary/merge.test.ts +41 -0
- package/tests/withValue.spec.ts +0 -1
package/dist/index.js
CHANGED
|
@@ -21,8 +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,
|
|
29
|
+
MapCardinality: () => MapCardinality,
|
|
26
30
|
Model: () => Model,
|
|
27
31
|
MutationIdentity: () => MutationIdentity,
|
|
28
32
|
and: () => and,
|
|
@@ -67,6 +71,8 @@ __export(src_exports, {
|
|
|
67
71
|
kvToDict: () => kvToDict,
|
|
68
72
|
literal: () => literal,
|
|
69
73
|
mapTo: () => mapTo,
|
|
74
|
+
mapToDict: () => mapToDict,
|
|
75
|
+
mapToFn: () => mapToFn,
|
|
70
76
|
mapValues: () => mapValues,
|
|
71
77
|
nameLiteral: () => nameLiteral,
|
|
72
78
|
not: () => not,
|
|
@@ -126,6 +132,14 @@ var valueTypes = {
|
|
|
126
132
|
literalArray: (arr) => [arr, true]
|
|
127
133
|
};
|
|
128
134
|
|
|
135
|
+
// src/types/dictionary/MapTo.ts
|
|
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 || {});
|
|
142
|
+
|
|
129
143
|
// src/utility/keys.ts
|
|
130
144
|
function keys(obj, ...without) {
|
|
131
145
|
const v = without.length > 0 ? Object.keys(obj).filter((k) => !without.includes(k)) : Object.keys(obj);
|
|
@@ -579,14 +593,68 @@ function mapValues(obj, valueMapper) {
|
|
|
579
593
|
}
|
|
580
594
|
|
|
581
595
|
// src/utility/dictionary/mapTo.ts
|
|
582
|
-
var
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
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;
|
|
617
|
+
if (isArray2) {
|
|
618
|
+
return source.flatMap(map);
|
|
619
|
+
} else {
|
|
620
|
+
return map(source);
|
|
621
|
+
}
|
|
622
|
+
};
|
|
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
|
+
});
|
|
636
|
+
var mapToFn = (map) => {
|
|
637
|
+
return mapper(DEFAULT_ONE_TO_MANY_MAPPING)(map);
|
|
638
|
+
};
|
|
639
|
+
var mapToDict = {
|
|
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);
|
|
588
655
|
}
|
|
589
656
|
};
|
|
657
|
+
var mapTo = createFnWithProps(mapToFn, mapToDict);
|
|
590
658
|
|
|
591
659
|
// src/utility/dictionary/strArrayToDict.ts
|
|
592
660
|
function strArrayToDict(...strings) {
|
|
@@ -752,8 +820,12 @@ function Model(name) {
|
|
|
752
820
|
// Annotate the CommonJS export names for ESM import in node:
|
|
753
821
|
0 && (module.exports = {
|
|
754
822
|
Configurator,
|
|
823
|
+
DEFAULT_MANY_TO_ONE_MAPPING,
|
|
824
|
+
DEFAULT_ONE_TO_MANY_MAPPING,
|
|
825
|
+
DEFAULT_ONE_TO_ONE_MAPPING,
|
|
755
826
|
ExplicitFunction,
|
|
756
827
|
FluentConfigurator,
|
|
828
|
+
MapCardinality,
|
|
757
829
|
Model,
|
|
758
830
|
MutationIdentity,
|
|
759
831
|
and,
|
|
@@ -798,6 +870,8 @@ function Model(name) {
|
|
|
798
870
|
kvToDict,
|
|
799
871
|
literal,
|
|
800
872
|
mapTo,
|
|
873
|
+
mapToDict,
|
|
874
|
+
mapToFn,
|
|
801
875
|
mapValues,
|
|
802
876
|
nameLiteral,
|
|
803
877
|
not,
|
package/dist/index.mjs
CHANGED
|
@@ -41,6 +41,14 @@ var valueTypes = {
|
|
|
41
41
|
literalArray: (arr) => [arr, true]
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
+
// src/types/dictionary/MapTo.ts
|
|
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
|
+
|
|
44
52
|
// src/utility/keys.ts
|
|
45
53
|
function keys(obj, ...without) {
|
|
46
54
|
const v = without.length > 0 ? Object.keys(obj).filter((k) => !without.includes(k)) : Object.keys(obj);
|
|
@@ -494,14 +502,68 @@ function mapValues(obj, valueMapper) {
|
|
|
494
502
|
}
|
|
495
503
|
|
|
496
504
|
// src/utility/dictionary/mapTo.ts
|
|
497
|
-
var
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
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;
|
|
526
|
+
if (isArray2) {
|
|
527
|
+
return source.flatMap(map);
|
|
528
|
+
} else {
|
|
529
|
+
return map(source);
|
|
530
|
+
}
|
|
531
|
+
};
|
|
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
|
+
});
|
|
545
|
+
var mapToFn = (map) => {
|
|
546
|
+
return mapper(DEFAULT_ONE_TO_MANY_MAPPING)(map);
|
|
547
|
+
};
|
|
548
|
+
var mapToDict = {
|
|
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);
|
|
503
564
|
}
|
|
504
565
|
};
|
|
566
|
+
var mapTo = createFnWithProps(mapToFn, mapToDict);
|
|
505
567
|
|
|
506
568
|
// src/utility/dictionary/strArrayToDict.ts
|
|
507
569
|
function strArrayToDict(...strings) {
|
|
@@ -666,8 +728,12 @@ function Model(name) {
|
|
|
666
728
|
}
|
|
667
729
|
export {
|
|
668
730
|
Configurator,
|
|
731
|
+
DEFAULT_MANY_TO_ONE_MAPPING,
|
|
732
|
+
DEFAULT_ONE_TO_MANY_MAPPING,
|
|
733
|
+
DEFAULT_ONE_TO_ONE_MAPPING,
|
|
669
734
|
ExplicitFunction,
|
|
670
735
|
FluentConfigurator,
|
|
736
|
+
MapCardinality,
|
|
671
737
|
Model,
|
|
672
738
|
MutationIdentity,
|
|
673
739
|
and,
|
|
@@ -712,6 +778,8 @@ export {
|
|
|
712
778
|
kvToDict,
|
|
713
779
|
literal,
|
|
714
780
|
mapTo,
|
|
781
|
+
mapToDict,
|
|
782
|
+
mapToFn,
|
|
715
783
|
mapValues,
|
|
716
784
|
nameLiteral,
|
|
717
785
|
not,
|
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";
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { UnionToTuple } from "../type-conversion";
|
|
2
|
+
|
|
3
|
+
export type OneToOne = `1:1`;
|
|
4
|
+
export type OneToMany = `1:M`;
|
|
5
|
+
export type OneToZero = `1:0`;
|
|
6
|
+
export type ZeroToOne = `0:1`;
|
|
7
|
+
export type ZeroToMany = `0:M`;
|
|
8
|
+
export type ZeroToZero = `0:0`;
|
|
9
|
+
export type ManyToMany = "M:M";
|
|
10
|
+
export type ManyToOne = "M:1";
|
|
11
|
+
export type ManyToZero = "M:0";
|
|
12
|
+
|
|
13
|
+
export type CardinalityNode = "0" | "1" | "M";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Cardinality which expects a singular input and requires
|
|
17
|
+
* 1 or many outputs.
|
|
18
|
+
*
|
|
19
|
+
* Note: choose `CardinalityFilter1` if you want to allow output
|
|
20
|
+
* to have no outputs.
|
|
21
|
+
*/
|
|
22
|
+
export type Cardinality1 = OneToOne | OneToMany;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Cardinality which expects a singular input and maps to 0,
|
|
26
|
+
* 1, or many outputs.
|
|
27
|
+
*/
|
|
28
|
+
export type CardinalityFilter1 = OneToOne | OneToMany | OneToZero;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Cardinality which expects a singular input which is allowed to be
|
|
32
|
+
* _undefined_ or the expected type.
|
|
33
|
+
*/
|
|
34
|
+
export type Cardinality0 = ZeroToOne | ZeroToMany | OneToOne | OneToMany;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Cardinality which expects a singular input -- which is allowed to be
|
|
38
|
+
* _undefined_ -- and maps to 0,
|
|
39
|
+
* 1, or many outputs.
|
|
40
|
+
*/
|
|
41
|
+
export type CardinalityFilter0 =
|
|
42
|
+
| ZeroToOne
|
|
43
|
+
| ZeroToMany
|
|
44
|
+
| OneToOne
|
|
45
|
+
| OneToMany
|
|
46
|
+
| OneToZero
|
|
47
|
+
| ZeroToZero;
|
|
48
|
+
|
|
49
|
+
export type CardinalityExplicit = `${number}:${number}`;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Cardinality of any sort between two types
|
|
53
|
+
*/
|
|
54
|
+
export type Cardinality =
|
|
55
|
+
| CardinalityFilter0
|
|
56
|
+
| CardinalityFilter1
|
|
57
|
+
| ManyToMany
|
|
58
|
+
| ManyToOne
|
|
59
|
+
| ManyToZero
|
|
60
|
+
| CardinalityExplicit;
|
|
61
|
+
|
|
62
|
+
export type CardinalityTuple<T extends Cardinality> = UnionToTuple<T>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The first or _input_ part of the Cardinality relationship
|
|
66
|
+
*/
|
|
67
|
+
export type CardinalityIn<T extends Cardinality> = T extends `${infer IN}:${string}` ? IN : never;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The second or _output_ part of the Cardinality relationship
|
|
71
|
+
*/
|
|
72
|
+
export type CardinalityOut<T extends Cardinality> = T extends `${string}:${infer OUT}`
|
|
73
|
+
? OUT
|
|
74
|
+
: never;
|
|
75
|
+
|
|
76
|
+
export type CardinalityInput<T, C extends Cardinality> = CardinalityTuple<C>[0] extends 0
|
|
77
|
+
? T | undefined
|
|
78
|
+
: CardinalityTuple<C>[0] extends 1
|
|
79
|
+
? T
|
|
80
|
+
: T[];
|
|
@@ -9,6 +9,7 @@ export * from "./CamelCase";
|
|
|
9
9
|
export * from "./CapitalizeWords";
|
|
10
10
|
export * from "./DashToSnake";
|
|
11
11
|
export * from "./DashUppercase";
|
|
12
|
+
export * from "./Cardinality";
|
|
12
13
|
export * from "./Dasherize";
|
|
13
14
|
export * from "./HasUppercase";
|
|
14
15
|
export * from "./IsCapitalized";
|