inferred-types 0.37.0 → 0.37.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/dist/index.d.ts +2745 -0
- package/dist/index.js +854 -0
- package/package.json +8 -13
- package/.eslintrc +0 -77
- package/.github/workflows/main.yml +0 -34
- package/.github/workflows/other.yml +0 -15
- package/.nvmrc +0 -1
- package/.prettierrc.js +0 -3
- package/.vscode/launch.json +0 -27
- package/.vscode/settings.json +0 -19
- package/devops/build.js +0 -243
- package/docs/builder-overview.md +0 -45
- package/docs/builder.md +0 -94
- package/src/errors/ReadOnlyViolation.ts +0 -3
- package/src/errors/index.ts +0 -12
- package/src/index.ts +0 -14
- package/src/runtime/README.md +0 -3
- package/src/runtime/api/api.ts +0 -10
- package/src/runtime/api/index.ts +0 -12
- package/src/runtime/builders/Model.ts +0 -25
- package/src/runtime/builders/url.ts +0 -15
- package/src/runtime/combinators/and.ts +0 -15
- package/src/runtime/combinators/filter.ts +0 -267
- package/src/runtime/combinators/index.ts +0 -4
- package/src/runtime/combinators/not.ts +0 -15
- package/src/runtime/combinators/or.ts +0 -5
- package/src/runtime/createFnWithProps.ts +0 -37
- package/src/runtime/dictionary/arrayToKeyLookup.ts +0 -19
- package/src/runtime/dictionary/defineProperties.ts +0 -35
- package/src/runtime/dictionary/dictArr.ts +0 -69
- package/src/runtime/dictionary/dictionaryTransform.ts +0 -22
- package/src/runtime/dictionary/entries.ts +0 -33
- package/src/runtime/dictionary/index.ts +0 -21
- package/src/runtime/dictionary/kv/dictToKv.ts +0 -21
- package/src/runtime/dictionary/kv/filterDictArray.ts +0 -31
- package/src/runtime/dictionary/kv/index.ts +0 -15
- package/src/runtime/dictionary/kv/kv.ts +0 -18
- package/src/runtime/dictionary/kv/kvToDict.ts +0 -24
- package/src/runtime/dictionary/mapTo.ts +0 -206
- package/src/runtime/dictionary/mapValues.ts +0 -23
- package/src/runtime/dictionary/merge.ts +0 -36
- package/src/runtime/dictionary/strArrayToDict.ts +0 -12
- package/src/runtime/index.ts +0 -23
- package/src/runtime/keys.ts +0 -16
- package/src/runtime/lists/asArray.ts +0 -38
- package/src/runtime/lists/createConverter.ts +0 -62
- package/src/runtime/lists/groupBy.ts +0 -15
- package/src/runtime/lists/index.ts +0 -15
- package/src/runtime/literals/ExplicitFunction.ts +0 -10
- package/src/runtime/literals/Suggest.ts +0 -19
- package/src/runtime/literals/arrayToObject.ts +0 -78
- package/src/runtime/literals/box.ts +0 -98
- package/src/runtime/literals/defineType.ts +0 -20
- package/src/runtime/literals/ensureLeading.ts +0 -17
- package/src/runtime/literals/ensureTrailing.ts +0 -17
- package/src/runtime/literals/identity.ts +0 -12
- package/src/runtime/literals/index.ts +0 -23
- package/src/runtime/literals/literal.ts +0 -48
- package/src/runtime/literals/pathJoin.ts +0 -33
- package/src/runtime/literals/stripLeading.ts +0 -15
- package/src/runtime/literals/stripTrailing.ts +0 -15
- package/src/runtime/literals/wide.ts +0 -13
- package/src/runtime/ruleset.ts +0 -42
- package/src/runtime/runtime/README.md +0 -3
- package/src/runtime/runtime/condition.ts +0 -13
- package/src/runtime/runtime/index.ts +0 -16
- package/src/runtime/runtime/type.ts +0 -127
- package/src/runtime/runtime/withValue.ts +0 -39
- package/src/runtime/state/Configurator.ts +0 -76
- package/src/runtime/state/FluentConfigurator.ts +0 -49
- package/src/runtime/state/index.ts +0 -13
- package/src/runtime/type-checks/ifSameType.ts +0 -20
- package/src/runtime/type-checks/ifTypeOf.ts +0 -124
- package/src/runtime/type-checks/index.ts +0 -24
- package/src/runtime/type-checks/isArray.ts +0 -34
- package/src/runtime/type-checks/isBoolean.ts +0 -24
- package/src/runtime/type-checks/isFalse.ts +0 -29
- package/src/runtime/type-checks/isFunction.ts +0 -26
- package/src/runtime/type-checks/isNull.ts +0 -26
- package/src/runtime/type-checks/isNumber.ts +0 -20
- package/src/runtime/type-checks/isObject.ts +0 -22
- package/src/runtime/type-checks/isString.ts +0 -34
- package/src/runtime/type-checks/isSymbol.ts +0 -3
- package/src/runtime/type-checks/isTrue.ts +0 -31
- package/src/runtime/type-checks/isUndefined.ts +0 -33
- package/src/runtime/type-checks/startsWith.ts +0 -107
- package/src/runtime/valueTypes.ts +0 -48
- package/src/types/Api.ts +0 -16
- package/src/types/Constructor.ts +0 -5
- package/src/types/EnumValues.ts +0 -14
- package/src/types/ExpandRecursively.ts +0 -12
- package/src/types/FunctionType.ts +0 -19
- package/src/types/If.ts +0 -10
- package/src/types/Include.ts +0 -18
- package/src/types/KeyedRecord.ts +0 -21
- package/src/types/Keys.ts +0 -26
- package/src/types/Length.ts +0 -8
- package/src/types/Mutable.ts +0 -8
- package/src/types/Narrowable.ts +0 -5
- package/src/types/Not.ts +0 -13
- package/src/types/Numeric.ts +0 -20
- package/src/types/Opaque.ts +0 -11
- package/src/types/README.md +0 -3
- package/src/types/Retain.ts +0 -16
- package/src/types/SimplifyObject.ts +0 -12
- package/src/types/Transformer.ts +0 -15
- package/src/types/TypeGuard.ts +0 -7
- package/src/types/Where.ts +0 -40
- package/src/types/alphabetic/AllCaps.ts +0 -15
- package/src/types/alphabetic/CamelCase.ts +0 -3
- package/src/types/alphabetic/CapFirstAlpha.ts +0 -23
- package/src/types/alphabetic/CapitalizeWords.ts +0 -9
- package/src/types/alphabetic/Cardinality.ts +0 -80
- package/src/types/alphabetic/DashToSnake.ts +0 -3
- package/src/types/alphabetic/DashUppercase.ts +0 -19
- package/src/types/alphabetic/Dasherize.ts +0 -23
- package/src/types/alphabetic/EnsureLeading.ts +0 -24
- package/src/types/alphabetic/EnsureTrailing.ts +0 -24
- package/src/types/alphabetic/HasUppercase.ts +0 -16
- package/src/types/alphabetic/IsCapitalized.ts +0 -18
- package/src/types/alphabetic/KebabCase.ts +0 -13
- package/src/types/alphabetic/LowerAllCaps.ts +0 -5
- package/src/types/alphabetic/PascalCase.ts +0 -29
- package/src/types/alphabetic/PathJoin.ts +0 -54
- package/src/types/alphabetic/Pluralize.ts +0 -112
- package/src/types/alphabetic/SnakeCase.ts +0 -27
- package/src/types/alphabetic/StripLeading.ts +0 -23
- package/src/types/alphabetic/StripTrailing.ts +0 -23
- package/src/types/alphabetic/Url.ts +0 -29
- package/src/types/alphabetic/alpha-characters.ts +0 -81
- package/src/types/alphabetic/index.ts +0 -32
- package/src/types/append-types.ts +0 -10
- package/src/types/boolean-logic/EndsWith.ts +0 -40
- package/src/types/boolean-logic/Extends.ts +0 -22
- package/src/types/boolean-logic/HasParameters.ts +0 -21
- package/src/types/boolean-logic/Includes.ts +0 -33
- package/src/types/boolean-logic/IsLiteral.ts +0 -101
- package/src/types/boolean-logic/IsScalar.ts +0 -20
- package/src/types/boolean-logic/IsUndefined.ts +0 -20
- package/src/types/boolean-logic/Or.ts +0 -12
- package/src/types/boolean-logic/StartsWith.ts +0 -42
- package/src/types/boolean-logic/TypeDefault.ts +0 -58
- package/src/types/boolean-logic/array.ts +0 -57
- package/src/types/boolean-logic/boolean.ts +0 -84
- package/src/types/boolean-logic/equivalency.ts +0 -15
- package/src/types/boolean-logic/index.ts +0 -14
- package/src/types/boolean-logic/object.ts +0 -30
- package/src/types/boolean-logic/string.ts +0 -21
- package/src/types/dictionary/DictChangeValue.ts +0 -34
- package/src/types/dictionary/DictPartialApplication.ts +0 -30
- package/src/types/dictionary/DictPrependWithFn.ts +0 -23
- package/src/types/dictionary/DictReturnValues.ts +0 -27
- package/src/types/dictionary/Get.ts +0 -14
- package/src/types/dictionary/MapTo.ts +0 -428
- package/src/types/dictionary/MutableProps.ts +0 -19
- package/src/types/dictionary/RequireProps.ts +0 -15
- package/src/types/dictionary/SameKeys.ts +0 -11
- package/src/types/dictionary/index.ts +0 -21
- package/src/types/dictionary/props.ts +0 -145
- package/src/types/fluent/fluent.ts +0 -61
- package/src/types/fluent/index.ts +0 -12
- package/src/types/functions/FinalReturn.ts +0 -12
- package/src/types/functions/LogicFunction.ts +0 -4
- package/src/types/functions/index.ts +0 -13
- package/src/types/index.ts +0 -49
- package/src/types/kv/DictFromKv.ts +0 -3
- package/src/types/kv/KeyValue.ts +0 -12
- package/src/types/kv/KvFrom.ts +0 -8
- package/src/types/kv/KvTuple.ts +0 -14
- package/src/types/kv/index.ts +0 -15
- package/src/types/lists/AfterFirst.ts +0 -10
- package/src/types/lists/ConvertAndMap.ts +0 -152
- package/src/types/lists/FilterTuple.ts +0 -20
- package/src/types/lists/First.ts +0 -8
- package/src/types/lists/FirstString.ts +0 -4
- package/src/types/lists/Split.ts +0 -21
- package/src/types/lists/UniqueForProp.ts +0 -18
- package/src/types/lists/index.ts +0 -18
- package/src/types/literal-unions/OptRequired.ts +0 -4
- package/src/types/literal-unions/index.ts +0 -1
- package/src/types/maybe.ts +0 -9
- package/src/types/ruleset-types.ts +0 -76
- package/src/types/runtime.ts +0 -39
- package/src/types/string-literals/Break.ts +0 -22
- package/src/types/string-literals/Concat.ts +0 -9
- package/src/types/string-literals/LeftWhitespace.ts +0 -13
- package/src/types/string-literals/Replace.ts +0 -17
- package/src/types/string-literals/RightWhitespace.ts +0 -13
- package/src/types/string-literals/StringLength.ts +0 -34
- package/src/types/string-literals/Trim.ts +0 -15
- package/src/types/string-literals/TrimLeft.ts +0 -14
- package/src/types/string-literals/TrimRight.ts +0 -14
- package/src/types/string-literals/form-fields.ts +0 -15
- package/src/types/string-literals/index.ts +0 -21
- package/src/types/tuples/DictArray.ts +0 -21
- package/src/types/tuples/FirstKey.ts +0 -10
- package/src/types/tuples/FirstKeyValue.ts +0 -9
- package/src/types/tuples/FirstOfEach.ts +0 -13
- package/src/types/tuples/FromDictArray.ts +0 -14
- package/src/types/tuples/SecondOfEach.ts +0 -13
- package/src/types/tuples/index.ts +0 -17
- package/src/types/type-conversion/TupleToUnion.ts +0 -9
- package/src/types/type-conversion/UnionToIntersection.ts +0 -9
- package/src/types/type-conversion/UnionToTuple.ts +0 -20
- package/src/types/type-conversion/Widen.ts +0 -22
- package/src/types/type-conversion/index.ts +0 -16
- package/src/types/type-testing.ts +0 -14
- package/tests/CamelCase-spec.ts +0 -20
- package/tests/Configurator-spec.hold +0 -106
- package/tests/ExplicitFunction-spec.ts +0 -50
- package/tests/IncludeAndRetain-spec.ts +0 -67
- package/tests/Includes-spec.ts +0 -36
- package/tests/KebabCase-spec.ts +0 -21
- package/tests/PascalCase-spec.ts +0 -22
- package/tests/Pluralize-spec.ts +0 -23
- package/tests/SnakeCase-spec.ts +0 -21
- package/tests/Where.spec.ts +0 -38
- package/tests/arrayToKeyLookup-spec.ts +0 -17
- package/tests/arrayToObject-spec.ts +0 -115
- package/tests/boolean-logic/Contains.test.ts +0 -55
- package/tests/boolean-logic/HasParameters.ts +0 -29
- package/tests/boolean-logic/IsLiteral.spec.ts +0 -65
- package/tests/boolean-logic/boolean.spec.ts +0 -21
- package/tests/boolean-logic/filter.spec.ts +0 -52
- package/tests/constructor.spec.ts +0 -42
- package/tests/createFnWithProps.spec.ts +0 -14
- package/tests/data/SimpleTable.hold +0 -21
- package/tests/data/index.ts +0 -12
- package/tests/data/playlist.hold +0 -25
- package/tests/data/song.hold +0 -23
- package/tests/defineType-spec.ts +0 -57
- package/tests/dictionary/DictChangeValue.test.ts +0 -30
- package/tests/dictionary/DictPartialApplication.test.ts +0 -43
- package/tests/dictionary/DictReturnValues.test.ts +0 -36
- package/tests/dictionary/Get.spec.ts +0 -28
- package/tests/dictionary/IntersectingKeys.test.ts +0 -42
- package/tests/dictionary/MutableProps.test.ts +0 -30
- package/tests/dictionary/OptionalKeys.test.ts +0 -24
- package/tests/dictionary/PrependValuesWithFunction.test.ts +0 -34
- package/tests/dictionary/RequireProps.test.ts +0 -21
- package/tests/dictionary/RequiredKeys.test.ts +0 -53
- package/tests/dictionary/TypeDefault.test.ts +0 -76
- package/tests/dictionary/mapTo.test.ts +0 -388
- package/tests/dictionary/merge.test.ts +0 -41
- package/tests/dictionaryTransform-spec.ts +0 -280
- package/tests/ifTypeOf-spec.ts +0 -191
- package/tests/kv/KeyValue-spec.ts +0 -22
- package/tests/kv/SameKeys-spec.ts +0 -35
- package/tests/kv/dict-to-kv-and-back.spec.ts +0 -169
- package/tests/kv/entries-spec.ts +0 -65
- package/tests/kv/keys.spec.ts +0 -66
- package/tests/kv/kv-spec.ts +0 -20
- package/tests/lists/First.test.ts +0 -43
- package/tests/lists/Length.test.ts +0 -19
- package/tests/lists/Split.test.ts +0 -29
- package/tests/lists/UniqueForProp.spec.ts +0 -59
- package/tests/lists/asArray.test.ts +0 -109
- package/tests/lists/dictArr.test.ts +0 -110
- package/tests/literal-spec.ts +0 -82
- package/tests/literals/AllCaps.spec.ts +0 -33
- package/tests/literals/CamelCase.spec.ts +0 -109
- package/tests/literals/Dasherize.spec.ts +0 -107
- package/tests/literals/EnsureStripLeadingTrailing.test.ts +0 -79
- package/tests/literals/HasUppercase.spec.ts +0 -33
- package/tests/literals/PascalCase.spec.ts +0 -109
- package/tests/literals/PathJoin.test.ts +0 -111
- package/tests/literals/SnakeCase.spec.ts +0 -109
- package/tests/literals/box.test.ts +0 -85
- package/tests/literals/whitespace-capture.spec.ts +0 -60
- package/tests/mapValues-spec.ts +0 -50
- package/tests/props-spec.ts +0 -234
- package/tests/runtime/condition.spec.ts +0 -19
- package/tests/runtime/if-is.spec.ts +0 -390
- package/tests/runtime/map-and-convert.test.ts +0 -31
- package/tests/runtime/type.spec.ts +0 -190
- package/tests/strArrayToDict-spec.ts +0 -40
- package/tests/tuples/TupleToUnion.spec.ts +0 -20
- package/tests/withValue.spec.ts +0 -173
- package/tsconfig.json +0 -36
- package/vitest.config.ts +0 -17
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2745 @@
|
|
|
1
|
+
type ApiFunction<P extends any[], R extends any> = (...args: P) => R;
|
|
2
|
+
type FluentFunction<P extends any[], R extends any> = (...args: P) => R;
|
|
3
|
+
type ApiValue<V extends any> = V;
|
|
4
|
+
/**
|
|
5
|
+
* Expresses the API in a structured manner while making distinction
|
|
6
|
+
* between a function endpoint and a _fluent_ function endpoint.
|
|
7
|
+
*/
|
|
8
|
+
type Api<T extends object> = {
|
|
9
|
+
[K in keyof T]: T[K] extends (...args: any) => T ? FluentFunction<Parameters<T[K]>, ReturnType<T[K]>> : T[K] extends (...args: any) => any ? ApiFunction<Parameters<T[K]>, ReturnType<T[K]>> : ApiValue<T[K]>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Define a class constructor; allowing strong typing for constructor's parameters
|
|
14
|
+
* and the returned class structure.
|
|
15
|
+
*/
|
|
16
|
+
type Constructor<Ctor extends any[], Klass extends any> = new (...props: Ctor) => Klass;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Provides the values of an Typescript **enum**:
|
|
20
|
+
* ```ts
|
|
21
|
+
* enum Foo { foo, bar, baz };
|
|
22
|
+
* // "0" | "1" | "2"
|
|
23
|
+
* type NumerericEnum = EnumValues<Foo>;
|
|
24
|
+
* enum Bar { foo = "foey", bar = "barred" };
|
|
25
|
+
* // "foey" | "barred"
|
|
26
|
+
* type StringEnum = EnumValues<Bar>;
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* **Note:** combine with `Numeric` to get number based indexes
|
|
30
|
+
*/
|
|
31
|
+
type EnumValues<T extends string | number> = `${T}`;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Recursively goes over an object based structure and tries to reduce
|
|
35
|
+
* it down to just a simple key/value type.
|
|
36
|
+
*/
|
|
37
|
+
type ExpandRecursively<T> = T extends object ? T extends (...args: any[]) => any ? T : {
|
|
38
|
+
[K in keyof T]: ExpandRecursively<T[K]>;
|
|
39
|
+
} : T;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Returns the first values type in an array of values
|
|
43
|
+
*/
|
|
44
|
+
type First<T extends readonly any[]> = T[0] extends T[number] ? T[0] : never;
|
|
45
|
+
type FirstOrUndefined<T extends unknown> = T extends [unknown, ...[unknown]] ? First<T> : undefined;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* **FunctionType**
|
|
49
|
+
*
|
|
50
|
+
* Provides a way to correctly match for regular functions _and_ functions which
|
|
51
|
+
* also have a dictionary hash alongside the root function.
|
|
52
|
+
*
|
|
53
|
+
* - without the generic `T` specified it simply matches correctly on both plain functions as well as functions which also have properties on them (this is consistent to how runtime's `typeof` operator works)
|
|
54
|
+
* - with the generic you can specify the shape of the key/values
|
|
55
|
+
*/
|
|
56
|
+
type FunctionType<T extends {} = {}> = {} extends T ? Function | (Function & {
|
|
57
|
+
[key: string]: any;
|
|
58
|
+
}) : Function | (Function & T);
|
|
59
|
+
/**
|
|
60
|
+
* **FnShape**
|
|
61
|
+
*
|
|
62
|
+
* Simple way to express the shape of a function's arguments and return type.
|
|
63
|
+
*/
|
|
64
|
+
type FnShape<A extends any[] = any[], R extends any = any> = (...args: A) => R;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Provides a unary condition for the type system:
|
|
68
|
+
* ```ts
|
|
69
|
+
* // "a"
|
|
70
|
+
* type T = If<true, "a", "b'>;
|
|
71
|
+
* // "b"
|
|
72
|
+
* type F = If<false, "a", "b">;
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
type If<C extends boolean, T, F> = C extends T ? C | F : never;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* **Include<T, U, L>**
|
|
79
|
+
*
|
|
80
|
+
* _Allows_ any value `T` which extends `U` otherwise sets type to `never`. Normally, you'll just ignore
|
|
81
|
+
* the `L` generic but if need the comparison to be literal you can set to `true`:
|
|
82
|
+
*
|
|
83
|
+
* ```ts
|
|
84
|
+
* const foo: "foo" = "foo";
|
|
85
|
+
* // "foo"
|
|
86
|
+
* type Normal = Include<typeof foo, string>;
|
|
87
|
+
* // L1 is never, L2 is "foo"
|
|
88
|
+
* type L1 = Include<typeof foo, string, true>;
|
|
89
|
+
* type L2 = Include<typeof foo, "foo", true>;
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
type Include<T, U, L extends boolean = false> = L extends true ? T extends U ? U extends T ? T : never : never : T extends U ? T : never;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* A "KeyedRecord" is intended to store a value without
|
|
96
|
+
* losing any ability to infer type information later.
|
|
97
|
+
*
|
|
98
|
+
* The structure is always represented as a two-key
|
|
99
|
+
* dictionary, where one key is always `__key` and the value
|
|
100
|
+
* of this key points to the second key.
|
|
101
|
+
*
|
|
102
|
+
* For example:
|
|
103
|
+
* ```ts
|
|
104
|
+
* const song: KeyedRecord = { __key: "song", song: XXX }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
type KeyedRecord<K extends string, V extends any, T extends {
|
|
108
|
+
__key: K;
|
|
109
|
+
} = {
|
|
110
|
+
__key: K;
|
|
111
|
+
}, U extends keyof T = keyof T & K> = {
|
|
112
|
+
[X in U]: T[X];
|
|
113
|
+
} & {
|
|
114
|
+
K: V;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* A Utility class that provides the same functionality as the built-in
|
|
119
|
+
* `keyof` TS operator but can also:
|
|
120
|
+
*
|
|
121
|
+
* - receive an array of strings and convert that into a union type.
|
|
122
|
+
* - you can exclude literal string from the returned result
|
|
123
|
+
*
|
|
124
|
+
* ```ts
|
|
125
|
+
* const t1 = { foo: 1, bar: 2 };
|
|
126
|
+
* // "foo" | "bar"
|
|
127
|
+
* type K = Keys<typeof t1>;
|
|
128
|
+
* const t2 = ["foo", "bar"] as const;
|
|
129
|
+
* // "foo" | "bar"
|
|
130
|
+
* type K = Keys<typeof t2>;
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
type Keys<T extends Record<string, any> | readonly string[], W extends string | undefined = undefined> = T extends readonly string[] ? W extends string ? Exclude<T[number], W> : T[number] : W extends string ? Exclude<keyof T & string, W> : keyof T & string;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Utility type which returns the length of an array literal
|
|
137
|
+
*
|
|
138
|
+
* ```ts
|
|
139
|
+
* type Three = Length<[ "a", "b", "c" ]>;
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
type Length<T extends readonly any[]> = T["length"];
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* **Equal**`<X,Y>`
|
|
146
|
+
*
|
|
147
|
+
* Type utility which tests whether two types -- `X` and `Y` -- are exactly the same type
|
|
148
|
+
*/
|
|
149
|
+
type IsEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
|
|
150
|
+
/**
|
|
151
|
+
* **NotEqual**`<X,Y>`
|
|
152
|
+
*
|
|
153
|
+
* Type utility which tests whether two types -- `X` and `Y` -- are _not_ exactly the same type
|
|
154
|
+
*/
|
|
155
|
+
type NotEqual<X, Y> = true extends IsEqual<X, Y> ? false : true;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* **AfterFirst**`<T>`
|
|
159
|
+
*
|
|
160
|
+
* returns the elements in an array _after_ the first element
|
|
161
|
+
*/
|
|
162
|
+
type AfterFirst<T extends readonly any[]> = T extends readonly [any, ...any[]] ? T extends readonly [any, ...infer Rest] ? Rest : never : T;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* returns the first `string` value from an array of values
|
|
166
|
+
*/
|
|
167
|
+
type FirstString<T> = T extends [infer S extends string, ...unknown[]] ? S : never;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* **FilterTuple**
|
|
171
|
+
*
|
|
172
|
+
* Allows a known tuple `T` to be _filtered down_ by eliminating all items
|
|
173
|
+
* in the Tuple that _extend_ type `F`
|
|
174
|
+
* ```ts
|
|
175
|
+
* type T = [1,"foo",3];
|
|
176
|
+
* // [1,3]
|
|
177
|
+
* type T2 = FilterTuple<T, string>;
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
type FilterTuple<TTuple extends any[] | readonly any[], TFilter, Result extends any[] = []> = TTuple extends [infer A, ...infer R] ? [A] extends [TFilter] ? FilterTuple<R, TFilter, Result> : FilterTuple<R, TFilter, [...Result, A]> : Result;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* **Split**`<T, SEP>`
|
|
184
|
+
*
|
|
185
|
+
* Splits a string literal `T` by string literal _separator_ `SEP`. The result is an array
|
|
186
|
+
* of string literals.
|
|
187
|
+
*/
|
|
188
|
+
type Split<T extends string, SEP extends string, ANSWER extends string[] = []> = string extends T ? string[] : T extends SEP ? ANSWER : T extends `${infer HEAD}${SEP}${infer TAIL}` ? Split<TAIL, SEP, [...ANSWER, HEAD]> : [...ANSWER, T];
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Get the type of a property of an object:
|
|
192
|
+
* ```ts
|
|
193
|
+
* const car = { make: "Chevy", model: "Malibu", }
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
type Get<T, K> = K extends `${infer FK}.${infer L}` ? FK extends keyof T ? Get<T[FK], L> : never : K extends keyof T ? T[K] : never;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* A union of types used in conjunction with the `literalValues()` function
|
|
200
|
+
* to produce a _narrow_ type definition of a passed in dictionary object.
|
|
201
|
+
*/
|
|
202
|
+
type Narrowable = string | number | boolean | symbol | object | undefined | void | null | {};
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Create a union type based on a given property in an array of objects
|
|
206
|
+
* ```ts
|
|
207
|
+
* const data = [
|
|
208
|
+
* { id: 123, color: "blue" },
|
|
209
|
+
* { id: 456, color: "red" },
|
|
210
|
+
* ] as const;
|
|
211
|
+
* // 123 | 456
|
|
212
|
+
* type U = UniqueForProp<typeof data, "id">;
|
|
213
|
+
* ```
|
|
214
|
+
*/
|
|
215
|
+
type UniqueForProp<T extends readonly Record<string, Narrowable>[], P extends string> = Readonly<Get<T[number], P>>;
|
|
216
|
+
|
|
217
|
+
type IsArray<T> = [T] extends [any[]] ? true : [T] extends [readonly any[]] ? true : false;
|
|
218
|
+
type IsReadonlyArray<T> = T extends readonly any[] ? true : false;
|
|
219
|
+
/**
|
|
220
|
+
* **IfArray**`<T, IF, ELSE>`
|
|
221
|
+
*
|
|
222
|
+
* Type utility which convert to type `IF` or `ELSE` based on whether `T` is an array
|
|
223
|
+
*/
|
|
224
|
+
type IfArray<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable> = IsArray<T> extends true ? IF : ELSE;
|
|
225
|
+
/**
|
|
226
|
+
* **IfArray**`<T, IF, ELSE>`
|
|
227
|
+
*
|
|
228
|
+
* Type utility which convert to type `IF` or `ELSE` based on whether `T` is a readonly array
|
|
229
|
+
*/
|
|
230
|
+
type IfReadonlyArray<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable> = IsReadonlyArray<T> extends true ? IF : ELSE;
|
|
231
|
+
/**
|
|
232
|
+
* **Contains**`<T, A>`
|
|
233
|
+
*
|
|
234
|
+
* Type utility which checks whether a type `T` exists within an array `A`. Result is
|
|
235
|
+
* `true` if `T` _extends_ any element in `A` making it match widely against `A`. If you
|
|
236
|
+
* prefer a narrower match you can use `NarrowlyContains<T,A>` instead.
|
|
237
|
+
*/
|
|
238
|
+
type Contains<T extends Narrowable, A extends readonly any[]> = First<A> extends T ? true : [] extends AfterFirst<A> ? false : Contains<T, AfterFirst<A>>;
|
|
239
|
+
/**
|
|
240
|
+
* **NarrowlyContains**`<T, A>`
|
|
241
|
+
*
|
|
242
|
+
* Type utility which checks whether a type `T` exists within an array `A`. Result is
|
|
243
|
+
* `true` if `T` _extends_ any element in `A` making it match widely against `A`. If you
|
|
244
|
+
* prefer a wider match you can use `Contains<T,A>` instead.
|
|
245
|
+
*/
|
|
246
|
+
type NarrowlyContains<T extends Narrowable, A extends readonly any[]> = IsEqual<First<A>, T> extends true ? true : [] extends AfterFirst<A> ? false : NarrowlyContains<T, AfterFirst<A>>;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Converts a Tuple type into a _union_ of the tuple elements
|
|
250
|
+
* ```ts
|
|
251
|
+
* const arr = [1, 3, 5] as const;
|
|
252
|
+
* // 1 | 3 | 5
|
|
253
|
+
* type U = TupleToUnion<typeof arr>;
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
type TupleToUnion<T> = T extends readonly any[] ? T[number] : never;
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* UnionToIntersection<{ foo: string } | { bar: string }> =
|
|
260
|
+
* { foo: string } & { bar: string }.
|
|
261
|
+
*/
|
|
262
|
+
type UnionToIntersection<U> = (U extends unknown ? (arg: U) => 0 : never) extends (arg: infer I) => 0 ? I : never;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* LastInUnion<1 | 2> = 2.
|
|
266
|
+
*/
|
|
267
|
+
type LastInUnion<U> = UnionToIntersection<U extends unknown ? (x: U) => 0 : never> extends (x: infer L) => 0 ? L : never;
|
|
268
|
+
/**
|
|
269
|
+
* UnionToTuple<1 | 2> = [1, 2].
|
|
270
|
+
*/
|
|
271
|
+
type UnionToTuple<U, Last = LastInUnion<U>> = [U] extends [never] ? [] : [...UnionToTuple<Exclude<U, Last>>, Last];
|
|
272
|
+
|
|
273
|
+
declare function createFnWithProps<F extends Function, P extends {}>(fn: F, props: P): F & P;
|
|
274
|
+
/**
|
|
275
|
+
* Adds a dictionary of key/value pairs to a function.
|
|
276
|
+
*/
|
|
277
|
+
declare function fnWithProps<A extends any[], R extends any, P extends {}>(fn: ((...args: A) => R), props: P): ((...args: A) => R) & P;
|
|
278
|
+
/**
|
|
279
|
+
* Adds read-only (and narrowly typed) key/value pairs to a function
|
|
280
|
+
*/
|
|
281
|
+
declare function readonlyFnWithProps<A extends any[], R extends any, N extends Narrowable, P extends Record<keyof P, N>>(fn: ((...args: A) => R), props: P): ((...args: A) => R) & Readonly<P>;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Provides the _keys_ of an object with the `keyof T` made explicit.
|
|
285
|
+
*/
|
|
286
|
+
declare function keys<T extends {}, W extends readonly string[]>(obj: T, ...without: W): Length<W> extends 0 ? (keyof T)[] : Exclude<keyof T, Keys<W, undefined>>[];
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* **ruleSet**
|
|
290
|
+
*
|
|
291
|
+
* Defines a ruleset composed of _dynamic_ and _static_ boolean operators.
|
|
292
|
+
*
|
|
293
|
+
* - the first function call defines _dynamic_ props (_optional_)
|
|
294
|
+
* - the second function call defines static values
|
|
295
|
+
*
|
|
296
|
+
* ```ts
|
|
297
|
+
* const rs = ruleSet(
|
|
298
|
+
* r => r.state()( { maybe: r => r.extends({ foo: 1 }) })
|
|
299
|
+
* )(
|
|
300
|
+
* { color: true, age: false }
|
|
301
|
+
* );
|
|
302
|
+
* ```
|
|
303
|
+
*/
|
|
304
|
+
declare function ruleSet<N extends Narrowable, TState extends Record<keyof TState, N>>(defn?: TState): TState | undefined;
|
|
305
|
+
|
|
306
|
+
declare const api: <N extends Narrowable, TPrivate extends Readonly<Record<any, N>>>(priv: TPrivate) => <TPublic extends object>(pub: TPublic) => () => TPublic;
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* A type utility which looks at a chain for functions and reduces the type
|
|
310
|
+
* to the final `ReturnType` of the chain.
|
|
311
|
+
*
|
|
312
|
+
* ```ts
|
|
313
|
+
* // number
|
|
314
|
+
* type T = FinalReturn<() => (foo: string) => (bar: string) => () => number>;
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
type FinalReturn<T extends any> = T extends (...args: any[]) => any ? FinalReturn<ReturnType<T>> : T;
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* A function which returns a boolean value
|
|
321
|
+
*/
|
|
322
|
+
type LogicFunction<T extends readonly any[]> = (...args: T) => boolean;
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Groups a number of "logic functions" together by combining their results using
|
|
326
|
+
* the logical **AND** operator.
|
|
327
|
+
*
|
|
328
|
+
* **Note:** a "logic function" is any function which returns a boolean
|
|
329
|
+
*/
|
|
330
|
+
declare const and: <T extends any[]>(...ops: readonly LogicFunction<T>[]) => LogicFunction<T>;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* **Or**`<T>`
|
|
334
|
+
*
|
|
335
|
+
* Takes an array of boolean values and produces a boolean OR across these values
|
|
336
|
+
*/
|
|
337
|
+
type Or<T extends readonly boolean[]> = NarrowlyContains<true, T> extends true ? true : NarrowlyContains<boolean, T> extends true ? boolean : false;
|
|
338
|
+
|
|
339
|
+
declare function or<O extends readonly boolean[]>(...conditions: O): Or<O>;
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Groups a number of "logic functions" together by combining their results using
|
|
343
|
+
* the logical **NOT** operator.
|
|
344
|
+
*
|
|
345
|
+
* **Note:** a "logic function" is any function which returns a boolean
|
|
346
|
+
*/
|
|
347
|
+
declare const not: <T extends any[]>(op: LogicFunction<T>) => LogicFunction<T>;
|
|
348
|
+
|
|
349
|
+
type FilterStarts = {
|
|
350
|
+
/** one or more string which the value is allowed to start with */
|
|
351
|
+
startsWith: string | string[];
|
|
352
|
+
};
|
|
353
|
+
type FilterIs = {
|
|
354
|
+
/** whether a string _**is**_ of a particular value */
|
|
355
|
+
is: string | string[];
|
|
356
|
+
};
|
|
357
|
+
type FilterEnds = {
|
|
358
|
+
endsWith: string | string[];
|
|
359
|
+
};
|
|
360
|
+
type FilterContains = {
|
|
361
|
+
/** whether any of the strings specified are _contained_ in the value */
|
|
362
|
+
contains: string | string[];
|
|
363
|
+
};
|
|
364
|
+
type FilterEquals = {
|
|
365
|
+
/** one or more values which _equal_ the value passed in */
|
|
366
|
+
equals: number | number[];
|
|
367
|
+
};
|
|
368
|
+
type FilterNotEqual = {
|
|
369
|
+
/** one or more values which ALL _do not equal_ the value passed in */
|
|
370
|
+
notEqual: number | number[];
|
|
371
|
+
};
|
|
372
|
+
type FilterGreaterThan = {
|
|
373
|
+
/** the incoming value is greater than this value */
|
|
374
|
+
greaterThan: number;
|
|
375
|
+
};
|
|
376
|
+
type FilterLessThan = {
|
|
377
|
+
/** the incoming value is less than this value */
|
|
378
|
+
lessThan: number;
|
|
379
|
+
};
|
|
380
|
+
type StringFilter = FilterIs | FilterStarts | FilterEnds | FilterContains | (FilterStarts & FilterEnds) | (FilterStarts & FilterContains) | (FilterEnds & FilterContains) | (FilterStarts & FilterEnds & FilterContains);
|
|
381
|
+
type NumericFilter = FilterEquals | FilterNotEqual | FilterGreaterThan | FilterLessThan | (FilterEquals & FilterNotEqual) | (FilterEquals & FilterGreaterThan) | (FilterEquals & FilterLessThan) | (FilterNotEqual & FilterGreaterThan) | (FilterNotEqual & FilterLessThan) | (FilterGreaterThan & FilterLessThan) | (FilterEquals & FilterGreaterThan & FilterLessThan) | (FilterNotEqual & FilterGreaterThan & FilterLessThan) | (FilterEquals & FilterNotEqual & FilterGreaterThan & FilterLessThan);
|
|
382
|
+
type FilterDefn = StringFilter | NumericFilter;
|
|
383
|
+
type NotFilter = {
|
|
384
|
+
/**
|
|
385
|
+
* **not**
|
|
386
|
+
*
|
|
387
|
+
* If you want to build a filter who's conditions being met results in _filtering_
|
|
388
|
+
* the value rather than accepting it then choose this.
|
|
389
|
+
*/
|
|
390
|
+
not: FilterDefn;
|
|
391
|
+
};
|
|
392
|
+
declare function isNotFilter(f: FilterDefn | NotFilter): f is NotFilter;
|
|
393
|
+
type UnwrapNot<T extends FilterDefn | NotFilter> = T extends NotFilter ? T["not"] extends StringFilter ? StringFilter : NumericFilter : T;
|
|
394
|
+
declare function isNumericFilter(filter: FilterDefn): filter is NumericFilter;
|
|
395
|
+
type UndefinedValue<U extends boolean> = true extends U ? "undefined treated as 'true'" : U extends "no-impact" ? "undefined treated in no-impact fashion" : "undefined treated as 'false'";
|
|
396
|
+
type UndefinedTreatment = "undefined treated as 'true'" | "undefined treated as 'false'";
|
|
397
|
+
type LogicalCombinator = "AND" | "OR";
|
|
398
|
+
/**
|
|
399
|
+
* **FilterFn**
|
|
400
|
+
*
|
|
401
|
+
* A filter function derived from the `filter()` configurator. This function is intended to provide a type-strong _filter_ function which can be used like so:
|
|
402
|
+
* be used like:
|
|
403
|
+
* ```ts
|
|
404
|
+
* const onlyPrivate = filter({ startsWith: "_" });
|
|
405
|
+
* const privateFiles = files.filter(onlyPrivate);
|
|
406
|
+
* ```
|
|
407
|
+
*/
|
|
408
|
+
type FilterFn<T extends StringFilter | NumericFilter> = T extends StringFilter ? <V extends string | undefined>(input: V) => boolean : <V extends number | undefined>(input: V) => boolean;
|
|
409
|
+
/**
|
|
410
|
+
* Defines a logical function for each condition type
|
|
411
|
+
*/
|
|
412
|
+
type ConditionFilter<T extends StringFilter | NumericFilter> = T extends StringFilter ? (input: string) => boolean : (input: number) => boolean;
|
|
413
|
+
/**
|
|
414
|
+
* **filter**
|
|
415
|
+
*
|
|
416
|
+
* A higher order helper utility which builds a boolean _filter_ function based on a simple
|
|
417
|
+
* configuration object. Support either _string_ or _numeric_ filters.
|
|
418
|
+
*
|
|
419
|
+
* ```ts
|
|
420
|
+
* const str = filter({startsWith: ["_", "."], endsWith: ".md"});
|
|
421
|
+
* const num = filter({ greaterThan: 55, notEqual: [66, 77]});
|
|
422
|
+
* ```
|
|
423
|
+
*
|
|
424
|
+
* All conditions (e.g., `startsWith`, `contains`, `notEqual`, etc.) that a particular filter
|
|
425
|
+
* is defined as having -- if there is more than one -- will be logically combined using AND
|
|
426
|
+
* unless specified otherwise in the third parameter.
|
|
427
|
+
*
|
|
428
|
+
* How a value of _undefined_ will be treated is stated in the second parameter but defaults
|
|
429
|
+
* to "no-impact" which means it's `false` when the logicCombinator is OR but defaults
|
|
430
|
+
* to `true` when the logicCombinator is AND.
|
|
431
|
+
*/
|
|
432
|
+
declare const filter: <F extends FilterDefn | NotFilter, U extends boolean | "no-impact", C extends LogicalCombinator>(config: F, logicCombinator?: C, ifUndefined?: U) => FilterFn<UnwrapNot<F>>;
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Passing in an array of strings, you are passed back a dictionary with
|
|
436
|
+
* all the keys being the strings and values set to `true`.
|
|
437
|
+
* ```ts
|
|
438
|
+
* // { bar: true, bar: true } as const;
|
|
439
|
+
* const d - dictArr(arr);
|
|
440
|
+
*
|
|
441
|
+
* const fooBar = arrayToKeyLookup("foo", "bar");
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
444
|
+
declare function arrayToKeyLookup<T extends readonly string[]>(...keys: T): Record<T[number], true>;
|
|
445
|
+
|
|
446
|
+
interface DefinePropertiesApi<T extends {}> {
|
|
447
|
+
/**
|
|
448
|
+
* Makes a property on the object **readonly** on the Javascript runtime
|
|
449
|
+
*/
|
|
450
|
+
ro<K extends keyof T>(prop: K, errorMsg?: (p: K, v: any) => string): Omit<T, K> & Record<K, Readonly<T[K]>>;
|
|
451
|
+
/**
|
|
452
|
+
* Makes a property on the object **read/writeable** on the Javascript runtime;
|
|
453
|
+
* this is the default so only use this where it is needed.
|
|
454
|
+
*/
|
|
455
|
+
rw<K extends keyof T>(prop: K): Omit<T, K> & Record<K, Readonly<T[K]>>;
|
|
456
|
+
}
|
|
457
|
+
declare function defineProperties<T extends {}>(obj: T): DefinePropertiesApi<T>;
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Often when mutating the shape of an object you will end up with the union of a number of
|
|
461
|
+
* `Record<string, x>` and `Record<string, y>` which is messy to look at and take away meaning.
|
|
462
|
+
*
|
|
463
|
+
* This type utility will cleanup an object and return a simple dictionary definition for it.
|
|
464
|
+
*/
|
|
465
|
+
type SimplifyObject<T extends {}> = ExpandRecursively<UnionToIntersection<ExpandRecursively<T>>>;
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Given a dictionary of key/values, where the value is a function, this
|
|
469
|
+
* type utility will maintain the keys but change the values to whatever
|
|
470
|
+
* the `ReturnType` of the function was.
|
|
471
|
+
* ```ts
|
|
472
|
+
* const api = {
|
|
473
|
+
* val: 42,
|
|
474
|
+
* hi: (name: string) => `hi ${name}`,
|
|
475
|
+
* bye: (name: string) => `bye ${name}`
|
|
476
|
+
* };
|
|
477
|
+
* // { hi: string; bye: string }
|
|
478
|
+
* type Test = UnwrapValue<typeof api>
|
|
479
|
+
* // { val: number; foo: string; bar: string }
|
|
480
|
+
* type Test2 = UnwrapValue<typeof api, false>
|
|
481
|
+
* ```
|
|
482
|
+
*/
|
|
483
|
+
type DictPartialApplication<T extends Record<string, any>, I extends boolean = true> = SimplifyObject<{
|
|
484
|
+
[K in keyof T]: T[K] extends (...args: any[]) => any ? Record<K, ReturnType<T[K]>> : true extends I ? never : Record<K, T[K]>;
|
|
485
|
+
}[keyof T]>;
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Allow a dictionary have it's value's type changed to `T` while maintaining the keys in
|
|
489
|
+
* the original object `I` so long as the original value for the KV pair extends `V`.
|
|
490
|
+
*
|
|
491
|
+
* If `V` is not specified then it defaults to _any_ and therefore all KVs are preserved.
|
|
492
|
+
*
|
|
493
|
+
* ```ts
|
|
494
|
+
* type Obj = { foo: "hello", bar: 42, baz: () => "world" };
|
|
495
|
+
* // { foo: number, bar: number, baz: number };
|
|
496
|
+
* type AllNumbers = DictChangeValue<Obj, number>;
|
|
497
|
+
* // { foo: number }
|
|
498
|
+
* type StringToBool = DictChangeValue<Obj, boolean, string>
|
|
499
|
+
* ```
|
|
500
|
+
*/
|
|
501
|
+
type DictChangeValue<
|
|
502
|
+
/** the object who's value-type we're changing */
|
|
503
|
+
I extends Record<string, any>,
|
|
504
|
+
/** the return type that functions should be modified to have */
|
|
505
|
+
T extends any,
|
|
506
|
+
/**
|
|
507
|
+
*The type we expect in the value; if the value extends type `V` then the value will
|
|
508
|
+
* be converted to type `O`; if not then the KV pair will be discarded
|
|
509
|
+
*/
|
|
510
|
+
V extends any = any> = SimplifyObject<{
|
|
511
|
+
[K in keyof I]: I[K] extends V ? Record<K, T> : never;
|
|
512
|
+
}[keyof I]>;
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* **DictPrependWithFn**
|
|
516
|
+
*
|
|
517
|
+
* Given a strongly typed object `<T>`, this utility will inject a function call with
|
|
518
|
+
* arguments `<A>` and then return what had subsequently been the value of the property.
|
|
519
|
+
*
|
|
520
|
+
* Should you only want to apply this treatment to _some_ of the properties you can
|
|
521
|
+
* pass in a value `<E>` which will ensure that only properties which _extend_ `E` will be
|
|
522
|
+
* modified.
|
|
523
|
+
*/
|
|
524
|
+
type DictPrependWithFn<T extends Record<string, any>, A extends any[], E extends any = any> = SimplifyObject<{
|
|
525
|
+
[K in keyof T]: T[K] extends E ? Record<K, (...args: A) => T[K]> : Record<K, T[K]>;
|
|
526
|
+
}[keyof T]>;
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* **DictReturnValues**
|
|
530
|
+
*
|
|
531
|
+
* A type utility which receives an object `<T>` and then modifies
|
|
532
|
+
* the return type of any properties which are a function to have this
|
|
533
|
+
* new **ReturnType** `<R>`. Optionally you can specify a particular return type which
|
|
534
|
+
* you are targeting and then
|
|
535
|
+
*/
|
|
536
|
+
type DictReturnValues<
|
|
537
|
+
/** the object which we expect to have props with function values */
|
|
538
|
+
T extends Record<string, any>,
|
|
539
|
+
/** the return type that functions should be modified to have */
|
|
540
|
+
R extends any,
|
|
541
|
+
/** optionally this utility can target only functions with a certain existing return value */
|
|
542
|
+
O extends (...args: any[]) => any = (...args: any[]) => any> = SimplifyObject<{
|
|
543
|
+
[K in keyof T]: T[K] extends O ? T[K] extends (...args: infer A) => any ? Record<K, (...args: A) => R> : Record<K, T[K]> : Record<K, T[K]>;
|
|
544
|
+
}[keyof T]>;
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Expresses whether an option is "opt" (optional) or "req" (required)
|
|
548
|
+
*/
|
|
549
|
+
type OptRequired = "opt" | "req";
|
|
550
|
+
|
|
551
|
+
declare const DEFAULT_ONE_TO_MANY_MAPPING: FinalizedMapConfig<"req", "I -> O[]", "opt">;
|
|
552
|
+
declare const DEFAULT_ONE_TO_ONE_MAPPING: FinalizedMapConfig<"req", "I -> O", "req">;
|
|
553
|
+
declare const DEFAULT_MANY_TO_ONE_MAPPING: FinalizedMapConfig<"req", "I[] -> O", "req">;
|
|
554
|
+
type DefaultOneToManyMapping = typeof DEFAULT_ONE_TO_MANY_MAPPING;
|
|
555
|
+
type DefaultOneToOneMapping = typeof DEFAULT_ONE_TO_ONE_MAPPING;
|
|
556
|
+
type DefaultManyToOneMapping = typeof DEFAULT_MANY_TO_ONE_MAPPING;
|
|
557
|
+
/**
|
|
558
|
+
* **mapTo** _utility_
|
|
559
|
+
*
|
|
560
|
+
* This utility -- by default -- creates a strongly typed 1:M data mapper which maps from one
|
|
561
|
+
* known source `I` to any array of another `O[]`:
|
|
562
|
+
* ```ts
|
|
563
|
+
* const mapper = mapTo<I, O>(i => [{
|
|
564
|
+
* foo: i.bar
|
|
565
|
+
* }]);
|
|
566
|
+
* ```
|
|
567
|
+
*/
|
|
568
|
+
declare const mapToFn: ConfiguredMap<DefaultOneToManyMapping>["map"];
|
|
569
|
+
/**
|
|
570
|
+
* Provides a `config` method which allows the relationships between _inputs_
|
|
571
|
+
* and _outputs_ to be configured.
|
|
572
|
+
*/
|
|
573
|
+
declare const mapToDict: MapperApi;
|
|
574
|
+
/**
|
|
575
|
+
* **mapTo** _utility_
|
|
576
|
+
*
|
|
577
|
+
* This utility creates a strongly typed data mapper which maps from one
|
|
578
|
+
* known source `I` to another `O`.
|
|
579
|
+
*
|
|
580
|
+
* Signatures:
|
|
581
|
+
* ```ts
|
|
582
|
+
* const defMap = mapTo<I,O>( ... );
|
|
583
|
+
* const configured = mapTo.config({ output: "req" }).map<I,O>( ... );
|
|
584
|
+
* const one2one = mapTo.oneToOne().map<I,O>( ... );
|
|
585
|
+
* const many2one = mapTo.manyToOne().map<I,O>( ... );
|
|
586
|
+
* ```
|
|
587
|
+
*/
|
|
588
|
+
declare const mapTo: (<I, O>(map: (source: I) => O[]) => Mapper<I, O, FinalizedMapConfig<"req", "I -> O[]", "opt">>) & MapperApi;
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* **Extends**`<T, EXTENDS>`
|
|
592
|
+
*
|
|
593
|
+
* Boolean type utility which returns `true` if `T` _extends_ `EXTENDS`.
|
|
594
|
+
*/
|
|
595
|
+
type Extends<T extends Narrowable, EXTENDS extends Narrowable> = T extends EXTENDS ? true : false;
|
|
596
|
+
/**
|
|
597
|
+
* **IfExtends**
|
|
598
|
+
*
|
|
599
|
+
* Branching type utility which returns type `IF` when `E` _extends_ `T`; otherwise
|
|
600
|
+
* it will return the type `ELSE`.
|
|
601
|
+
*/
|
|
602
|
+
type IfExtends<T extends Narrowable, EXTENDS extends Narrowable, IF extends Narrowable, ELSE extends Narrowable> = Extends<T, EXTENDS> extends true ? IF : ELSE;
|
|
603
|
+
|
|
604
|
+
type IsBoolean<T> = [T] extends [boolean] ? true : false;
|
|
605
|
+
/**
|
|
606
|
+
* Type utility which returns `true` or `false` based on
|
|
607
|
+
* whether the type holds the narrow "true" type.
|
|
608
|
+
* ```ts
|
|
609
|
+
* // true
|
|
610
|
+
* type T = IsTrue<true>;
|
|
611
|
+
* // boolean
|
|
612
|
+
* type U = IsTrue<boolean>;
|
|
613
|
+
* // false
|
|
614
|
+
* type F = IsTrue<false>;
|
|
615
|
+
* type F2 = IsTrue<"false">;
|
|
616
|
+
* ```
|
|
617
|
+
*/
|
|
618
|
+
type IsTrue<T extends Narrowable> = IsBoolean<T> extends true ? T extends true ? true : T extends false ? false : unknown : false;
|
|
619
|
+
type IsFalse<T extends Narrowable> = IsBoolean<T> extends true ? T extends false ? true : true extends T ? false : unknown : false;
|
|
620
|
+
/**
|
|
621
|
+
* Type utility which checks for literal `true` value and then switches type
|
|
622
|
+
* to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
|
|
623
|
+
* is the wide type of `boolean`
|
|
624
|
+
*/
|
|
625
|
+
type IfTrue<T extends boolean, IF extends Narrowable, ELSE extends Narrowable, MAYBE extends Narrowable> = IsTrue<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
|
|
626
|
+
/**
|
|
627
|
+
* Type utility which checks for literal `false` value and then switches type
|
|
628
|
+
* to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
|
|
629
|
+
* is the wide type of `boolean`
|
|
630
|
+
*/
|
|
631
|
+
type IfFalse<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable, MAYBE extends Narrowable> = IsFalse<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
|
|
632
|
+
/**
|
|
633
|
+
* **IsBooleanLiteral**
|
|
634
|
+
*
|
|
635
|
+
* Type utility which returns true/false if the boolean value is a _boolean literal_ versus
|
|
636
|
+
* just the wider _boolean_ type.
|
|
637
|
+
*/
|
|
638
|
+
type IsBooleanLiteral<T extends Narrowable> = IsTrue<T> extends true ? true : IsFalse<T> extends true ? true : false;
|
|
639
|
+
/**
|
|
640
|
+
* **IfBooleanLiteral**
|
|
641
|
+
*
|
|
642
|
+
* Branch utility which returns `IF` type when `T` is a boolean literal and `ELSE` otherwise
|
|
643
|
+
*/
|
|
644
|
+
type IfBooleanLiteral<T extends boolean, IF extends Narrowable, ELSE extends Narrowable> = IsBooleanLiteral<T> extends true ? IF : ELSE;
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* **IsStringLiteral**
|
|
648
|
+
*
|
|
649
|
+
* Type utility which returns true/false if the string a _string literal_ versus
|
|
650
|
+
* just the _string_ type.
|
|
651
|
+
*/
|
|
652
|
+
type IsStringLiteral<T extends Narrowable> = [T] extends [string] ? string extends T ? false : true : false;
|
|
653
|
+
/**
|
|
654
|
+
* **IfStringLiteral**
|
|
655
|
+
*
|
|
656
|
+
* Branch utility which returns `IF` type when `T` is a string literal and `ELSE` otherwise
|
|
657
|
+
*/
|
|
658
|
+
type IfStringLiteral<T extends string, IF extends Narrowable, ELSE extends Narrowable> = [
|
|
659
|
+
IsStringLiteral<T>
|
|
660
|
+
] extends [true] ? IF : ELSE;
|
|
661
|
+
/**
|
|
662
|
+
* **IsNumericLiteral**
|
|
663
|
+
*
|
|
664
|
+
* Type utility which returns true/false if the numeric value a _numeric literal_ versus
|
|
665
|
+
* just the _number_ type.
|
|
666
|
+
*/
|
|
667
|
+
type IsNumericLiteral<T extends number> = number extends T ? false : true;
|
|
668
|
+
/**
|
|
669
|
+
* **IfNumericLiteral**
|
|
670
|
+
*
|
|
671
|
+
* Branch utility which returns `IF` type when `T` is a numeric literal and `ELSE` otherwise
|
|
672
|
+
*/
|
|
673
|
+
type IfNumericLiteral<T extends number, IF extends Narrowable, ELSE extends Narrowable> = IsNumericLiteral<T> extends true ? IF : ELSE;
|
|
674
|
+
/**
|
|
675
|
+
* **IsLiteral**
|
|
676
|
+
*
|
|
677
|
+
* Type utility which returns true/false if the value passed -- a form of a
|
|
678
|
+
* string, number, or boolean -- is a _literal_ value of that type (true) or
|
|
679
|
+
* the more generic wide type (false).
|
|
680
|
+
*/
|
|
681
|
+
type IsLiteral<T> = [T] extends [string] ? IsStringLiteral<T> : [T] extends [boolean] ? IsBooleanLiteral<T> : [T] extends [number] ? IsNumericLiteral<T> : false;
|
|
682
|
+
/**
|
|
683
|
+
* **IsOptionalLiteral**
|
|
684
|
+
*
|
|
685
|
+
* Type utility which returns true/false if the value passed -- a form of a
|
|
686
|
+
* string, number, or boolean -- is a _literal_ value of that type (true) or
|
|
687
|
+
* the more generic wide type (false).
|
|
688
|
+
*
|
|
689
|
+
* This type also strips off _undefined_ from any possible union type to evaluate
|
|
690
|
+
* to `true` even when a literal value is in union with _undefined_. If you don't
|
|
691
|
+
* want to test for the union with _undefined_ use the `IsOptional` utility instead.
|
|
692
|
+
*/
|
|
693
|
+
type IsOptionalLiteral<T> = [Exclude<T, undefined>] extends [string] ? IsStringLiteral<Exclude<T, undefined>> : [Exclude<T, undefined>] extends [boolean] ? IsBooleanLiteral<Exclude<T, undefined>> : [Exclude<T, undefined>] extends [number] ? IsNumericLiteral<Exclude<T, undefined>> : false;
|
|
694
|
+
/**
|
|
695
|
+
* **IfLiteral**
|
|
696
|
+
*
|
|
697
|
+
* Branch type utility with return `IF` when `T` is a _literal_ value and `ELSE` otherwise
|
|
698
|
+
*/
|
|
699
|
+
type IfLiteral<T, IF extends Narrowable, ELSE extends Narrowable> = IsLiteral<T> extends true ? IF : ELSE;
|
|
700
|
+
/**
|
|
701
|
+
* **IfOptionalLiteral**
|
|
702
|
+
*
|
|
703
|
+
* Branch type utility with return `IF` when `T` is a _literal_ value (with possibly
|
|
704
|
+
* the inclusion of _undefined_); otherwise returns the type `ELSE`
|
|
705
|
+
*/
|
|
706
|
+
type IfOptionalLiteral<T, IF extends Narrowable, ELSE extends Narrowable> = IsOptionalLiteral<T> extends true ? IF : ELSE;
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* **IsUndefined**
|
|
710
|
+
*
|
|
711
|
+
* Boolean type utility returns `true` if `T` is undefined; `false` otherwise
|
|
712
|
+
*/
|
|
713
|
+
type IsUndefined<T extends Narrowable> = T extends undefined ? true : false;
|
|
714
|
+
/**
|
|
715
|
+
* **IfUndefined**`<T, IF, ELSE>`
|
|
716
|
+
*
|
|
717
|
+
* Type utility which returns `IF` type when `T` is an _undefined_
|
|
718
|
+
* otherwise returns `ELSE` type.
|
|
719
|
+
*/
|
|
720
|
+
type IfUndefined<T, IF extends Narrowable, ELSE extends Narrowable> = IsUndefined<T> extends true ? IF : ELSE;
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* **TypeDefault**
|
|
724
|
+
*
|
|
725
|
+
* A type utility designed to help maintain strong and narrow types where
|
|
726
|
+
* you have a value `T` which _might_ be **undefined** and a type `D` which
|
|
727
|
+
* defines all the _default_ type for `T`.
|
|
728
|
+
*
|
|
729
|
+
* - In all cases we compare first whether `T` is undefined and replace it's
|
|
730
|
+
* type with `D` 1-for-1 if it is
|
|
731
|
+
* - To address a larger set of use cases, when `D` _extends_ an object we will
|
|
732
|
+
* compare each property of `D` against `T`
|
|
733
|
+
* ```ts
|
|
734
|
+
* type I = { foo?: "foo" | undefined; bar?: 42 | 53 | undefined };
|
|
735
|
+
* type D = { foo: "foo"; bar: 53 };
|
|
736
|
+
* type DF = TypeDefault<I,D>; // `D`
|
|
737
|
+
* const i = { foo: undefined, bar: 99 } as const;
|
|
738
|
+
* type DF2 = TypeDefault<typeof i, D>; // `{ foo: "foo"; bar: 99 }`
|
|
739
|
+
* ```
|
|
740
|
+
*/
|
|
741
|
+
type TypeDefault<T, D> = IsObject<D> extends true ? IsObject<T> extends true ? SimplifyObject<{
|
|
742
|
+
[K in keyof D]: K extends keyof T ? TypeDefault<T[K], D[K]> : D[K];
|
|
743
|
+
}> : IfUndefined<T, // check if T is undefined
|
|
744
|
+
D, // use D as the type
|
|
745
|
+
Exclude<T, undefined>> : IfUndefined<T, // check whether is T is undefined
|
|
746
|
+
D, // assign to D if it is
|
|
747
|
+
IfOptionalLiteral<T, // if T is a literal
|
|
748
|
+
IfExtends<D, T, D, // use D since it extends the value of T
|
|
749
|
+
Exclude<T, undefined>>, Exclude<T, undefined>>>;
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Expresses relationship between inputs/outputs:
|
|
753
|
+
*/
|
|
754
|
+
declare enum MapCardinality {
|
|
755
|
+
/** every input results in 0:M outputs */
|
|
756
|
+
OneToMany = "I -> O[]",
|
|
757
|
+
/** every input results in 0:1 outputs */
|
|
758
|
+
OneToOne = "I -> O",
|
|
759
|
+
/** every input is an array of type I and reduced to a single O */
|
|
760
|
+
ManyToOne = "I[] -> O"
|
|
761
|
+
}
|
|
762
|
+
type MapCardinalityIllustrated = EnumValues<MapCardinality>;
|
|
763
|
+
/**
|
|
764
|
+
* The _user_ configuration of a **mapTo** mapper function
|
|
765
|
+
* which will be finalized by merging it with the appropriate
|
|
766
|
+
* default mapping type.
|
|
767
|
+
*/
|
|
768
|
+
interface MapConfig<IR extends OptRequired | undefined = undefined, D extends MapCardinalityIllustrated | undefined = undefined, OR extends OptRequired | undefined = undefined> {
|
|
769
|
+
input?: IR;
|
|
770
|
+
output?: OR;
|
|
771
|
+
cardinality?: D;
|
|
772
|
+
/**
|
|
773
|
+
* Whether calls to the final `MapFn` will be logged to stderr
|
|
774
|
+
* for debugging purposes. Defaults to false; if you specify
|
|
775
|
+
* a _string_ for a value that will be sent to stderr along
|
|
776
|
+
* with other debugging info.
|
|
777
|
+
*/
|
|
778
|
+
debug?: boolean | string;
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* A finalized configuration of a **mapTo** mapper functions cardinality
|
|
782
|
+
* relationships between _inputs_ and _outputs_.
|
|
783
|
+
*
|
|
784
|
+
* Note: _this configuration does _not_ yet include the actual mapping
|
|
785
|
+
* configuration between the input and output._
|
|
786
|
+
*/
|
|
787
|
+
type FinalizedMapConfig<IR extends OptRequired = MapIR<DefaultOneToManyMapping>, D extends MapCardinalityIllustrated = MapCard<DefaultOneToManyMapping>, OR extends OptRequired = MapOR<DefaultOneToManyMapping>> = Required<Omit<MapConfig<IR, D, OR>, "debug">> & {
|
|
788
|
+
finalized: true;
|
|
789
|
+
debug: boolean | string;
|
|
790
|
+
};
|
|
791
|
+
/**
|
|
792
|
+
* User configuration exposed by a config function which specifies the
|
|
793
|
+
* cardinality already (e.g., `oneToMany()`, `manyToOne()`)
|
|
794
|
+
*/
|
|
795
|
+
type MapCardinalityConfig<IR extends OptRequired | undefined, OR extends OptRequired | undefined> = {
|
|
796
|
+
/** whether we the input can _optionally_ be an `undefined` value or not */
|
|
797
|
+
input?: IR;
|
|
798
|
+
/** whether we the output can _optionally_ be an `undefined` value or not */
|
|
799
|
+
output?: OR;
|
|
800
|
+
/**
|
|
801
|
+
* Whether calls to the final `MapFn` will be logged to stderr
|
|
802
|
+
* for debugging purposes. Defaults to false; if you set to a string
|
|
803
|
+
* value than this will be echoed out with stderr.
|
|
804
|
+
*/
|
|
805
|
+
debug?: boolean | string;
|
|
806
|
+
};
|
|
807
|
+
/**
|
|
808
|
+
* **ConfiguredMap**
|
|
809
|
+
*
|
|
810
|
+
* A partial application of the mapTo() utility which has expressed the
|
|
811
|
+
* configuration of the _inputs_ and _outputs_ and provides a `.map()`
|
|
812
|
+
* method which allows the user configure the specifics of the mapping.
|
|
813
|
+
*/
|
|
814
|
+
type ConfiguredMap<C extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = {
|
|
815
|
+
map: <I, O>(map: MapTo<I, O, C>) => Mapper<I, O, C>;
|
|
816
|
+
input: MapIR<C>;
|
|
817
|
+
cardinality: MapCard<C>;
|
|
818
|
+
output: MapOR<C>;
|
|
819
|
+
debug: boolean | string;
|
|
820
|
+
};
|
|
821
|
+
/**
|
|
822
|
+
* Extracts the IR, Cardinality, and OR generics from a FinalizedMapConfig
|
|
823
|
+
*/
|
|
824
|
+
type DecomposeMapConfig<M extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = M extends MapConfig<infer IR, infer D, infer OR> ? IR extends OptRequired | undefined ? D extends MapCardinalityIllustrated | undefined ? OR extends OptRequired | undefined ? [IR, D, OR] : never : never : never : M extends FinalizedMapConfig<infer IR, infer D, infer OR> ? IR extends OptRequired ? D extends MapCardinalityIllustrated ? OR extends OptRequired ? [IR, D, OR] : never : never : never : never;
|
|
825
|
+
/** extracts IR from a `FinalizedMapConfig` */
|
|
826
|
+
type MapIR<T extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = DecomposeMapConfig<T>[0];
|
|
827
|
+
/**
|
|
828
|
+
* extracts the MapCardinality from a `FinalizedMapConfig`
|
|
829
|
+
*/
|
|
830
|
+
type MapCard<T extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = DecomposeMapConfig<T>[1];
|
|
831
|
+
/** extracts OR from a `FinalizedMapConfig` */
|
|
832
|
+
type MapOR<T extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = DecomposeMapConfig<T>[2];
|
|
833
|
+
/**
|
|
834
|
+
* Merges the types of a userland configuration with a default configuration
|
|
835
|
+
*/
|
|
836
|
+
type AsFinalizedConfig<U extends MapConfig<OptRequired | undefined, MapCardinalityIllustrated | undefined, OptRequired | undefined>, D extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = TypeDefault<U, D> extends FinalizedMapConfig<infer IR, infer C, infer OR> ? FinalizedMapConfig<IR, C, OR> : never;
|
|
837
|
+
type MapperApi = {
|
|
838
|
+
/**
|
|
839
|
+
* Provides opportunity to configure _input_, _output_, and _cardinality_
|
|
840
|
+
* prior to providing a mapping function.
|
|
841
|
+
*
|
|
842
|
+
* Note: _the defaults for configuration are defined by the_ `DEFAULT_ONE_TO_MANY_MAPPING`
|
|
843
|
+
* _constant made available as a symbol from this library._
|
|
844
|
+
*/
|
|
845
|
+
config: <C extends MapConfig<OptRequired, //
|
|
846
|
+
MapCardinalityIllustrated, OptRequired>>(config: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
847
|
+
DefaultOneToManyMapping>>;
|
|
848
|
+
/**
|
|
849
|
+
* Provides a nice 1:1 ratio between the input and output.
|
|
850
|
+
*
|
|
851
|
+
* By default the input and output are considered to be _required_
|
|
852
|
+
* properties but this can be changed with the options hash provided.
|
|
853
|
+
* ```ts
|
|
854
|
+
* const mapper = mapTo.oneToOne().map(...);
|
|
855
|
+
* // add in ability to filter out some inputs
|
|
856
|
+
* const mapAndFilter = mapTo.oneToOne({ output: "opt" })
|
|
857
|
+
* ```
|
|
858
|
+
*/
|
|
859
|
+
oneToOne: <C extends MapCardinalityConfig<OptRequired, OptRequired>>(config?: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
860
|
+
DefaultOneToOneMapping>>;
|
|
861
|
+
/**
|
|
862
|
+
* **manyToOne** _mapping_
|
|
863
|
+
*
|
|
864
|
+
* Provides a configuration where multiple inputs `I[]` will be mapped to a
|
|
865
|
+
* single output `O`.
|
|
866
|
+
*
|
|
867
|
+
* Choosing this configuration will, by default, set both input and output
|
|
868
|
+
* to be "required" but you can change this default if you so choose.
|
|
869
|
+
*/
|
|
870
|
+
manyToOne: <C extends MapCardinalityConfig<OptRequired | undefined, //
|
|
871
|
+
//
|
|
872
|
+
OptRequired | undefined>>(config?: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
873
|
+
DefaultManyToOneMapping>>;
|
|
874
|
+
oneToMany: <C extends MapCardinalityConfig<OptRequired | undefined, //
|
|
875
|
+
//
|
|
876
|
+
OptRequired | undefined>>(config?: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
877
|
+
DefaultOneToManyMapping>>;
|
|
878
|
+
};
|
|
879
|
+
type MapInput<I, //
|
|
880
|
+
IR extends OptRequired, C extends MapCardinalityIllustrated> = C extends MapCardinality.OneToMany | "I -> O[]" ? IR extends "opt" ? I | undefined : I : C extends MapCardinality.OneToOne | "I -> O" ? IR extends "opt" ? I | undefined : I : C extends MapCardinality.ManyToOne | "I[] -> O" ? IR extends "opt" ? I[] | undefined : I[] : never;
|
|
881
|
+
type MapOutput<O, //
|
|
882
|
+
OR extends OptRequired, C extends MapCardinalityIllustrated> = C extends MapCardinality.OneToMany | "I -> O[]" ? OR extends "opt" ? O[] : [O, ...O[]] : C extends MapCardinality.OneToOne | "I -> O" ? OR extends "opt" ? O | null : O : C extends MapCardinality.ManyToOne | "I[] -> O" ? OR extends "opt" ? O | null : O : never;
|
|
883
|
+
/**
|
|
884
|
+
* **MapTo<I, O>**
|
|
885
|
+
*
|
|
886
|
+
* A mapping function between an input type `I` and output type `O`. Defaults to using
|
|
887
|
+
* the _default_ OneToMany mapping config.
|
|
888
|
+
*
|
|
889
|
+
* **Note:** this type is designed to guide the userland mapping; refer
|
|
890
|
+
* to `MapFn` if you want the type output by the `mapFn()` utility.
|
|
891
|
+
*/
|
|
892
|
+
type MapTo<I, O, C extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired> = DefaultOneToManyMapping> = MapIR<C> extends "opt" ? (source?: MapInput<I, MapIR<C>, MapCard<C>>) => MapOutput<O, MapOR<C>, MapCard<C>> : (source: MapInput<I, MapIR<C>, MapCard<C>>) => MapOutput<O, MapOR<C>, MapCard<C>>;
|
|
893
|
+
type MapFnOutput<I, O, S, OR extends OptRequired, C extends MapCardinalityIllustrated> = C extends "I -> O[]" | MapCardinality.OneToMany ? S extends I[] ? OR extends "opt" ? O[] : [O, ...O[]] : OR extends "opt" ? O[] | null : O[] : C extends MapCardinality.OneToOne | "I -> O" ? S extends I[] ? OR extends "opt" ? O[] : [O, ...O[]] : OR extends "opt" ? O | null : O : C extends MapCardinality.ManyToOne | "I[] -> O" ? S extends I[][] ? OR extends "opt" ? O[] : [O, ...O[]] : OR extends "opt" ? O | null : O : never;
|
|
894
|
+
type MapFnInput<I, IR extends OptRequired, D extends MapCardinalityIllustrated> = D extends "I -> O[]" | MapCardinality.OneToMany ? IR extends "opt" ? I | I[] | undefined : I | I[] : D extends MapCardinality.OneToOne | "I -> O" ? IR extends "opt" ? I | I[] | undefined : I | I[] : D extends MapCardinality.ManyToOne | "I[] -> O" ? IR extends "opt" ? I[] | I[][] | undefined : I[] | I[][] : never;
|
|
895
|
+
/**
|
|
896
|
+
* The mapping function provided by the `mapFn()` utility. This _fn_
|
|
897
|
+
* is intended to be used in two ways:
|
|
898
|
+
*
|
|
899
|
+
* 1. Iterative:
|
|
900
|
+
* ```ts
|
|
901
|
+
* const m = mapTo<I,O>(i => [ ... ]);
|
|
902
|
+
* // maps inputs to outputs
|
|
903
|
+
* const out = inputs.map(m);
|
|
904
|
+
* ```
|
|
905
|
+
* 2. Block:
|
|
906
|
+
* ```ts
|
|
907
|
+
* // maps inputs to outputs (filtering or splitting where appr.)
|
|
908
|
+
* const out2 = m(inputs);
|
|
909
|
+
* ```
|
|
910
|
+
*/
|
|
911
|
+
type MapFn<I, O, C extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = MapIR<C> extends "opt" ? <S extends MapFnInput<I, MapIR<C>, MapCard<C>>>(source?: S) => MapFnOutput<I, O, S, MapOR<C>, MapCard<C>> : <S extends MapFnInput<I, MapIR<C>, MapCard<C>>>(source: S) => MapFnOutput<I, O, S, MapOR<C>, MapCard<C>>;
|
|
912
|
+
/**
|
|
913
|
+
* **Mapper**
|
|
914
|
+
*
|
|
915
|
+
* A fully configured _mapper_ stemming from the **mapTo()** utility. It is both a mapping
|
|
916
|
+
* function and a dictionary which describes the mapper's properties.
|
|
917
|
+
* ```ts
|
|
918
|
+
* const m = mapTo.oneToOne().map( ... );
|
|
919
|
+
* const mapped = m(inputs);
|
|
920
|
+
* const mappedOver = inputs.map(m);
|
|
921
|
+
* ```
|
|
922
|
+
*
|
|
923
|
+
* Note: the root of a `Mapper` is the mapper function but
|
|
924
|
+
* this is combined with a dictionary of settings and types
|
|
925
|
+
* which you can use. For instance, look at the `fnSignature`
|
|
926
|
+
* property to get the _type_ signature of the map function.
|
|
927
|
+
*/
|
|
928
|
+
type Mapper<I = unknown, O = unknown, C extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired> = FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = {
|
|
929
|
+
input: MapIR<C>;
|
|
930
|
+
output: MapOR<C>;
|
|
931
|
+
cardinality: MapCard<C>;
|
|
932
|
+
debug: boolean | string;
|
|
933
|
+
inputType: I;
|
|
934
|
+
outputType: O;
|
|
935
|
+
/**
|
|
936
|
+
* Provides the _type_ information for mapper function.
|
|
937
|
+
*
|
|
938
|
+
* Note: _this is just a **type**_ not the actual function which positioned
|
|
939
|
+
* at the root of the Mapper type
|
|
940
|
+
*/
|
|
941
|
+
fnSignature: MapFn<I, O, C>;
|
|
942
|
+
} & MapFn<I, O, C>;
|
|
943
|
+
/**
|
|
944
|
+
* **MapInputFrom**
|
|
945
|
+
*
|
|
946
|
+
* Type utility which extracts the `I` type from a fully configured `Mapper`
|
|
947
|
+
*/
|
|
948
|
+
type MapInputFrom<T extends Mapper> = T extends Mapper<infer I> ? I : never;
|
|
949
|
+
/**
|
|
950
|
+
* **MapOutputFrom**
|
|
951
|
+
*
|
|
952
|
+
* Type utility which extracts the output [`O`] type from a fully configured `Mapper`
|
|
953
|
+
*/
|
|
954
|
+
type MapOutputFrom<T extends Mapper> = T extends Mapper<any, infer O> ? O : never;
|
|
955
|
+
/**
|
|
956
|
+
* **MapCardinalityFrom**
|
|
957
|
+
*
|
|
958
|
+
* Type utility which extracts _cardinality_ of a `Mapper`'s inputs to outputs
|
|
959
|
+
*/
|
|
960
|
+
type MapCardinalityFrom<T extends Mapper> = T extends Mapper<any, any, infer C> ? C extends FinalizedMapConfig<OptRequired, infer Cardinality, OptRequired> ? Cardinality : never : never;
|
|
961
|
+
|
|
962
|
+
/**
|
|
963
|
+
* Given a dictionary of type `<T>`, this utility function will
|
|
964
|
+
* make the `<M>` generic property _mutable_ and all other _read-only_.
|
|
965
|
+
*
|
|
966
|
+
* ```ts
|
|
967
|
+
* // { foo: string, bar?: Readonly<number> }
|
|
968
|
+
* type Example = MutableProps<{
|
|
969
|
+
* foo: Readonly<string>,
|
|
970
|
+
* bar?: number
|
|
971
|
+
* }, "foo">;
|
|
972
|
+
* ```
|
|
973
|
+
*/
|
|
974
|
+
type MutableProps<T extends {}, M extends keyof T & string> = ExpandRecursively<Mutable<Pick<T, M>> & Readonly<Pick<T, Keys<T, M>>>>;
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* Given a dictionary of type `<T>`, this utility function will
|
|
978
|
+
* make the `<R>` generic property _required_ (use a union to make
|
|
979
|
+
* more than one prop required).
|
|
980
|
+
*
|
|
981
|
+
* ```ts
|
|
982
|
+
* // { foo: string, bar?: number }
|
|
983
|
+
* type Example = RequireProps<{foo?: string, bar?: number}, "foo">;
|
|
984
|
+
* ```
|
|
985
|
+
*/
|
|
986
|
+
type RequireProps<T extends {}, R extends keyof T> = ExpandRecursively<Required<Pick<T, R>> & T>;
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* **SameKeys**
|
|
990
|
+
*
|
|
991
|
+
* Creates a _type_ with the same _keys_ as `T` but sets all values of these keys to `A` (which is
|
|
992
|
+
* **any** by default).
|
|
993
|
+
*
|
|
994
|
+
* Note: meant to be used as part of an _extends_ clause in most cases.
|
|
995
|
+
*/
|
|
996
|
+
type SameKeys<T extends object, A extends any = any> = {
|
|
997
|
+
[P in keyof T]: A;
|
|
998
|
+
};
|
|
999
|
+
|
|
1000
|
+
type LowerAlpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
|
|
1001
|
+
/** Uppercase alphabetic character */
|
|
1002
|
+
type UpperAlpha = Uppercase<LowerAlpha>;
|
|
1003
|
+
/**
|
|
1004
|
+
* Alphabetical characters (upper and lower)
|
|
1005
|
+
*/
|
|
1006
|
+
type Alpha = UpperAlpha | LowerAlpha;
|
|
1007
|
+
type Whitespace = " " | "\n" | "\t";
|
|
1008
|
+
type Punctuation = "." | "," | ";" | "!" | "?";
|
|
1009
|
+
/**
|
|
1010
|
+
* Characters which typically are used to separate words (but not including a space)
|
|
1011
|
+
*/
|
|
1012
|
+
type StringDelimiter = "_" | "-" | "/" | "\\";
|
|
1013
|
+
type OpeningBracket = "(" | "[" | "{";
|
|
1014
|
+
type ClosingBracket = ")" | "]" | "}";
|
|
1015
|
+
/**
|
|
1016
|
+
* Opening and closing parenthesis
|
|
1017
|
+
*/
|
|
1018
|
+
type Parenthesis = "(" | ")";
|
|
1019
|
+
/**
|
|
1020
|
+
* Opening and closing brackets
|
|
1021
|
+
*/
|
|
1022
|
+
type Bracket = OpeningBracket | ClosingBracket;
|
|
1023
|
+
/**
|
|
1024
|
+
* Numeric string characters
|
|
1025
|
+
*/
|
|
1026
|
+
type NumericString = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
|
1027
|
+
/**
|
|
1028
|
+
* Any alphabetic or numeric string character
|
|
1029
|
+
*/
|
|
1030
|
+
type AlphaNumeric = Alpha | NumericString;
|
|
1031
|
+
/**
|
|
1032
|
+
* Allows alphanumeric characters and some special characters typically allowed
|
|
1033
|
+
* in variable names.
|
|
1034
|
+
*/
|
|
1035
|
+
type VariableName = AlphaNumeric | "_" | "." | "-";
|
|
1036
|
+
type SpecialCharacters = "@" | "~" | "^" | "#" | "&" | "*";
|
|
1037
|
+
/**
|
|
1038
|
+
* Non-alphabetic characters including whitespace, string numerals, and
|
|
1039
|
+
*/
|
|
1040
|
+
type NonAlpha = Whitespace | Punctuation | NumericString | Bracket | SpecialCharacters;
|
|
1041
|
+
type Ipv4 = `${number}.${number}.${number}.${number}`;
|
|
1042
|
+
|
|
1043
|
+
/**
|
|
1044
|
+
* Extracts the _required_ keys in the object's type. You also may
|
|
1045
|
+
* optionally filter by the _value_ of the key.
|
|
1046
|
+
*/
|
|
1047
|
+
type RequiredKeys<T extends object, V extends any = any> = {
|
|
1048
|
+
[K in keyof T]-?: {} extends {
|
|
1049
|
+
[P in K]: T[K];
|
|
1050
|
+
} ? never : T[K] extends V ? K : never;
|
|
1051
|
+
}[keyof T];
|
|
1052
|
+
/**
|
|
1053
|
+
* Extracts the intersecting/common keys to two objects
|
|
1054
|
+
*/
|
|
1055
|
+
type IntersectingKeys<T extends Record<string, any> | readonly string[], U extends Record<string, any> | readonly string[]> = {
|
|
1056
|
+
[K in keyof T]: K extends Keys<U> ? K : never;
|
|
1057
|
+
}[keyof T];
|
|
1058
|
+
/**
|
|
1059
|
+
* Extracts the _optional_ keys in the object's type. You also may
|
|
1060
|
+
* optionally filter by the _value_ of the key.
|
|
1061
|
+
*/
|
|
1062
|
+
type OptionalKeys<T extends object, V extends any = any> = {
|
|
1063
|
+
[K in keyof T]-?: {} extends {
|
|
1064
|
+
[P in K]: T[K];
|
|
1065
|
+
} ? V extends T[K] ? K : never : never;
|
|
1066
|
+
}[keyof T];
|
|
1067
|
+
/**
|
|
1068
|
+
* The _keys_ on a given object `T` which have a literal value of `W`.
|
|
1069
|
+
*
|
|
1070
|
+
* Optionally, you may provide a generic `E` to exclude certain keys in
|
|
1071
|
+
* result set.
|
|
1072
|
+
* ```ts
|
|
1073
|
+
* // "foo"
|
|
1074
|
+
* type Str = KeysWithValue<{ foo: "hi"; bar: 5 }>;
|
|
1075
|
+
* ```
|
|
1076
|
+
*/
|
|
1077
|
+
type KeysWithValue<W extends any, T extends object> = {
|
|
1078
|
+
[K in keyof T]: T[K] extends W ? Readonly<K> : never;
|
|
1079
|
+
}[keyof T];
|
|
1080
|
+
/**
|
|
1081
|
+
* A `PrivateKey` must start with a `_` character and then follow with
|
|
1082
|
+
* an alphabetic character
|
|
1083
|
+
*/
|
|
1084
|
+
type PrivateKey = `_${Alpha}${string}`;
|
|
1085
|
+
/**
|
|
1086
|
+
* Keys on an object which have a `_` character as first part of the
|
|
1087
|
+
* name are considered private and this utility will create a union
|
|
1088
|
+
* of all the keys in this category.
|
|
1089
|
+
*/
|
|
1090
|
+
type PrivateKeys<T extends object> = {
|
|
1091
|
+
[K in keyof T]: K extends `_${string}` ? K : never;
|
|
1092
|
+
}[keyof T];
|
|
1093
|
+
/**
|
|
1094
|
+
* **PublicKeys**
|
|
1095
|
+
*
|
|
1096
|
+
* Builds a union type of all keys which are "public" where a public
|
|
1097
|
+
* key is any key which _does not_ start with the `_` character.
|
|
1098
|
+
*/
|
|
1099
|
+
type PublicKeys<T extends object> = {
|
|
1100
|
+
[K in keyof T]: K extends `_${string}` ? never : K;
|
|
1101
|
+
}[keyof T];
|
|
1102
|
+
type StringKeys<T extends object> = {
|
|
1103
|
+
[K in keyof T]: K extends string ? Readonly<K> : never;
|
|
1104
|
+
}[keyof T];
|
|
1105
|
+
/**
|
|
1106
|
+
* The keys of an object which _are not_ a string type
|
|
1107
|
+
*/
|
|
1108
|
+
type NonStringKeys<T extends object> = {
|
|
1109
|
+
[K in keyof T]: K extends string ? never : Readonly<K>;
|
|
1110
|
+
}[keyof T];
|
|
1111
|
+
type NumericKeys<T extends object> = {
|
|
1112
|
+
[K in keyof T]: K extends number ? Readonly<K> : never;
|
|
1113
|
+
}[keyof T];
|
|
1114
|
+
type NonNumericKeys<T extends object> = {
|
|
1115
|
+
[K in keyof T]: K extends number ? never : Readonly<K>;
|
|
1116
|
+
}[keyof T];
|
|
1117
|
+
/**
|
|
1118
|
+
* **RequiredProps**
|
|
1119
|
+
*
|
|
1120
|
+
* Reduces an object type to only key/value pairs where the key is required
|
|
1121
|
+
*/
|
|
1122
|
+
type RequiredProps<T extends object> = Pick<T, RequiredKeys<T>>;
|
|
1123
|
+
/**
|
|
1124
|
+
* **OptionalProps**
|
|
1125
|
+
*
|
|
1126
|
+
* Reduces an object to only key/value pairs where the key is optional
|
|
1127
|
+
*/
|
|
1128
|
+
type OptionalProps<T extends object> = Pick<T, OptionalKeys<T>>;
|
|
1129
|
+
/**
|
|
1130
|
+
* **WithValue**
|
|
1131
|
+
*
|
|
1132
|
+
* Reduces an object's type down to only those key/value pairs where the
|
|
1133
|
+
* value is of type `W`.
|
|
1134
|
+
* ```ts
|
|
1135
|
+
* const foo = { a: 1, b: "hi", c: () => "hello" }
|
|
1136
|
+
* // { c: () => "hello" }
|
|
1137
|
+
* type W = WithValue<Function, typeof foo>
|
|
1138
|
+
* ```
|
|
1139
|
+
*/
|
|
1140
|
+
type WithValue<W extends any, T extends object, E extends any = undefined> = undefined extends E ? Pick<T, KeysWithValue<W, T>> : Omit<Pick<T, KeysWithValue<W, T>>, KeysWithValue<E, T>>;
|
|
1141
|
+
type DictionaryWithoutValue<TDict extends object, TWithoutValue> = Omit<TDict, KeysWithValue<TWithoutValue, TDict>>;
|
|
1142
|
+
/**
|
|
1143
|
+
* Reduces an object to only the key/value pairs where the key is a
|
|
1144
|
+
* string.
|
|
1145
|
+
*/
|
|
1146
|
+
type WithStringKeys<T extends object> = Omit<T, NonStringKeys<T>>;
|
|
1147
|
+
/**
|
|
1148
|
+
* Reduces an object to only the key/value pairs where the key is numeric.
|
|
1149
|
+
*/
|
|
1150
|
+
type WithNumericKeys<T extends object> = Omit<T, NonNumericKeys<T>>;
|
|
1151
|
+
|
|
1152
|
+
/**
|
|
1153
|
+
* **Transformer**
|
|
1154
|
+
*
|
|
1155
|
+
* A function responsible for transforming the _values_ of
|
|
1156
|
+
* dictionary `I` into different _values_ for dictionary `O`.
|
|
1157
|
+
*
|
|
1158
|
+
* This type utility assumes that _keys_ of both dictionaries
|
|
1159
|
+
* are the same.
|
|
1160
|
+
*/
|
|
1161
|
+
type Transformer<I extends object, O extends SameKeys<I>, K extends keyof I = keyof I> = (input: I, key: K) => O[K];
|
|
1162
|
+
|
|
1163
|
+
/**
|
|
1164
|
+
* Takes a dictionary of type `I` and converts it to a dictionary of type `O` where
|
|
1165
|
+
* they _keys_ used in both dictionaries are the same.
|
|
1166
|
+
*
|
|
1167
|
+
* The _transform_ function passed in must be able to recieve the full input object
|
|
1168
|
+
* and key, and then return expected value of `O` for the given key.
|
|
1169
|
+
*/
|
|
1170
|
+
declare function dictionaryTransform<I extends object, O extends SameKeys<I>>(input: I, transform: Transformer<I, O>): O;
|
|
1171
|
+
|
|
1172
|
+
interface Uniqueness<T> {
|
|
1173
|
+
/** boolean flag to indicate whether the property was unique across all records */
|
|
1174
|
+
isUnique: boolean;
|
|
1175
|
+
/** the overall number of records which contained the property */
|
|
1176
|
+
size: number;
|
|
1177
|
+
/** specifies if undefined values were encountered for this property */
|
|
1178
|
+
includedUndefined: boolean;
|
|
1179
|
+
/** the unique values for the property across all records */
|
|
1180
|
+
values: readonly T[];
|
|
1181
|
+
}
|
|
1182
|
+
type DictArrApi<T extends Record<string, Narrowable>, A extends readonly T[]> = {
|
|
1183
|
+
length: number;
|
|
1184
|
+
toLookup<PL extends RequiredKeys<T, string> & keyof T & string>(prop: PL): UniqueForProp<A, PL> extends string ? Record<UniqueForProp<A, PL>, T> : Record<string, T>;
|
|
1185
|
+
sum<PS extends RequiredKeys<T, number> | OptionalKeys<T, number>>(prop: PS): number;
|
|
1186
|
+
count<PC extends OptionalKeys<T>>(prop: PC): number;
|
|
1187
|
+
unique<PU extends Keys<T> & keyof T>(prop: PU): Uniqueness<T[PU]>;
|
|
1188
|
+
};
|
|
1189
|
+
/**
|
|
1190
|
+
* converts an array of objects to a dictionary with keys formed from a given property
|
|
1191
|
+
* of the object and the value being the object itself.
|
|
1192
|
+
*/
|
|
1193
|
+
declare const dictArr: <T extends Record<string, Narrowable>>(...dicts: readonly T[]) => DictArrApi<T, readonly T[]>;
|
|
1194
|
+
|
|
1195
|
+
type DictFromKv<T extends readonly {
|
|
1196
|
+
key: string;
|
|
1197
|
+
value: unknown;
|
|
1198
|
+
}[]> = {
|
|
1199
|
+
[R in T[number] as R["key"]]: R["value"];
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1202
|
+
/**
|
|
1203
|
+
* Provides a strongly typed _key_ and _value_ for a dictionary `T`
|
|
1204
|
+
*
|
|
1205
|
+
* ```ts
|
|
1206
|
+
* type Obj = { foo: 1, bar: "hi" };
|
|
1207
|
+
* // ["foo", 1 ]
|
|
1208
|
+
* type Foo = KeyValue<Obj, "foo">;
|
|
1209
|
+
* ```
|
|
1210
|
+
*/
|
|
1211
|
+
type KeyValue<T extends object, K extends keyof T> = [K & keyof T, ExpandRecursively<T[K]>];
|
|
1212
|
+
|
|
1213
|
+
/**
|
|
1214
|
+
* Type utility which takes an object type and converts to an array of KV objects:
|
|
1215
|
+
* ```ts
|
|
1216
|
+
* // [ {key: "id", value: 123 } | {key: "foo", value: "bar" } ][]
|
|
1217
|
+
* type Arr = KvFrom<{ id: 123, foo: "bar" }>;
|
|
1218
|
+
* ```
|
|
1219
|
+
*/
|
|
1220
|
+
type KvFrom<T extends object> = Array<{
|
|
1221
|
+
[K in keyof T]: {
|
|
1222
|
+
key: K;
|
|
1223
|
+
value: T[K];
|
|
1224
|
+
};
|
|
1225
|
+
}[keyof T]>;
|
|
1226
|
+
|
|
1227
|
+
/**
|
|
1228
|
+
* **KvTuple**
|
|
1229
|
+
*
|
|
1230
|
+
* a key/value of type `T` represented as `[key, kv]`
|
|
1231
|
+
*
|
|
1232
|
+
* ```ts
|
|
1233
|
+
* type Obj = { foo: 1, bar: "hi" };
|
|
1234
|
+
* // ["foo", { foo: 1 } ]
|
|
1235
|
+
* type Foo = KvTuple<Obj, "foo">;
|
|
1236
|
+
* ```
|
|
1237
|
+
*
|
|
1238
|
+
* **Note:** _consider use of `KeyValue<T,K>` as an alternate representation_
|
|
1239
|
+
*/
|
|
1240
|
+
type KvTuple<T, K extends keyof T> = [K, Record<K, T[K]>];
|
|
1241
|
+
|
|
1242
|
+
/**
|
|
1243
|
+
* **entries**
|
|
1244
|
+
*
|
|
1245
|
+
* Provides an _iterable_ over the passed in dictionary object where each iteration
|
|
1246
|
+
* provides a tuple of `[ key, value ]` which preserve type literals.
|
|
1247
|
+
*
|
|
1248
|
+
* For example:
|
|
1249
|
+
* ```ts
|
|
1250
|
+
* const obj = { foo: 1, bar: "hi" };
|
|
1251
|
+
* // k type is "foo" then "bar"; v type is 1 then "hi"
|
|
1252
|
+
* for (const [k, v] of entries(obj)) { ... }
|
|
1253
|
+
* ```
|
|
1254
|
+
*/
|
|
1255
|
+
declare function entries<N extends Narrowable, T extends Record<string, N>, I extends KeyValue<T, keyof T>>(obj: T): {
|
|
1256
|
+
[Symbol.iterator](): Generator<I, void, unknown>;
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1259
|
+
/**
|
|
1260
|
+
* **mapValues**
|
|
1261
|
+
*
|
|
1262
|
+
* Maps over a dictionary, preserving the keys but allowing the values to be mutated.
|
|
1263
|
+
*
|
|
1264
|
+
* ```ts
|
|
1265
|
+
* const colors = { red: 4, blue: 2, green: 3 };
|
|
1266
|
+
* // { red: 8, blue: 4, green: 6 }
|
|
1267
|
+
* const twoX = mapValues(colors, v => v * 2);
|
|
1268
|
+
* ```
|
|
1269
|
+
*/
|
|
1270
|
+
declare function mapValues<N extends Narrowable, T extends Record<string, N>, V>(obj: T, valueMapper: (k: T[keyof T]) => V): { [K in keyof T]: V; };
|
|
1271
|
+
|
|
1272
|
+
/**
|
|
1273
|
+
* converts an array of strings `["a", "b", "c"]` into a more type friendly
|
|
1274
|
+
* dictionary of the type `{ a: true, b: true, c: true }`
|
|
1275
|
+
*/
|
|
1276
|
+
declare function strArrayToDict<T extends readonly string[]>(...strings: T): ExpandRecursively<Record<T[number], true>>;
|
|
1277
|
+
|
|
1278
|
+
/**
|
|
1279
|
+
* Converts a dictionary object into an array of dictionaries with `key` and `value` properties
|
|
1280
|
+
* ```ts
|
|
1281
|
+
* // [ { key: "id", value: 123 }, { key: "foo", value: "bar" } ]
|
|
1282
|
+
* const arr = dictToKv({ id: 123, foo: "bar" });
|
|
1283
|
+
* ```
|
|
1284
|
+
*/
|
|
1285
|
+
declare function dictToKv<N extends Narrowable, T extends {
|
|
1286
|
+
[key: string]: N;
|
|
1287
|
+
}, U extends boolean>(obj: T, _makeTuple?: U): U extends true ? UnionToTuple<(Mutable<T> extends infer T_1 extends object ? { [K in keyof T_1]: {
|
|
1288
|
+
key: K;
|
|
1289
|
+
value: Mutable<T>[K];
|
|
1290
|
+
}; } : never)[keyof T], LastInUnion<(Mutable<T> extends infer T_1 extends object ? { [K in keyof T_1]: {
|
|
1291
|
+
key: K;
|
|
1292
|
+
value: Mutable<T>[K];
|
|
1293
|
+
}; } : never)[keyof T]>> : KvFrom<Mutable<T>>;
|
|
1294
|
+
|
|
1295
|
+
type DictArrayFilterCallback<K extends keyof T, T extends object, R extends true | false> = (key: K, value: Pick<T, K>) => R;
|
|
1296
|
+
/**
|
|
1297
|
+
* An element in a `DictArray` shaped as a two element tuple: `[key, kv]`.
|
|
1298
|
+
*/
|
|
1299
|
+
type DictArrayKv<K extends keyof T, T> = [K, Pick<T, K>];
|
|
1300
|
+
type DictKvTuple<K extends string> = [K, Record<K, unknown>];
|
|
1301
|
+
/**
|
|
1302
|
+
* A an array of `DictArrayKv` tuples which can be reconstructed
|
|
1303
|
+
* to a strongly typed dictionary object.
|
|
1304
|
+
* ```ts
|
|
1305
|
+
* const example: DictArray<{ foo: 1, bar: "hi" }> = [
|
|
1306
|
+
* [ "foo", { foo: 1 }],
|
|
1307
|
+
* [ "bar", { bar: "hi" }]
|
|
1308
|
+
* ]
|
|
1309
|
+
* ```
|
|
1310
|
+
*/
|
|
1311
|
+
type DictArray<T> = Array<{
|
|
1312
|
+
[K in keyof T]: DictArrayKv<K, T>;
|
|
1313
|
+
}[keyof T]>;
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* Returns the _first_ key in an object.
|
|
1317
|
+
*
|
|
1318
|
+
* **Note:** key order is not guarenteed so typically this is used
|
|
1319
|
+
* for a key/value pair where only one key is expected
|
|
1320
|
+
*/
|
|
1321
|
+
type FirstKey<T extends object> = UnionToTuple<Keys<T>>[0];
|
|
1322
|
+
|
|
1323
|
+
/**
|
|
1324
|
+
* Utility type which operates on a dictionary and provides the **value** of the
|
|
1325
|
+
* `First<T>` key of the dictionary. Because dictionary's don't provide assurances
|
|
1326
|
+
* about key order, this is typically only used in cases where it's known there is
|
|
1327
|
+
* a single key on the object.
|
|
1328
|
+
*/
|
|
1329
|
+
type FirstKeyValue<T extends object> = FirstKey<T> extends keyof T ? T[FirstKey<T>] : never;
|
|
1330
|
+
|
|
1331
|
+
/**
|
|
1332
|
+
* For a two-dimensional array, returns a _union type_ which combines the first element of the interior
|
|
1333
|
+
* array.
|
|
1334
|
+
*
|
|
1335
|
+
* ```ts
|
|
1336
|
+
* const test = [ ["foo", 1], ["bar", 2] ];
|
|
1337
|
+
* // "foo" | "bar"
|
|
1338
|
+
* type F = FirstOfEach<typeof test>;
|
|
1339
|
+
* ```
|
|
1340
|
+
*/
|
|
1341
|
+
type FirstOfEach<T extends readonly any[][]> = T[number][0] extends T[number][number] ? T[number][0] : never;
|
|
1342
|
+
|
|
1343
|
+
/**
|
|
1344
|
+
* Typescript utility which receives `T` as shape which resembles `DictArray<D>`
|
|
1345
|
+
* and if the type `D` can be inferred it is returned.
|
|
1346
|
+
* ```ts
|
|
1347
|
+
* // { foo: 1; bar: "hi" }
|
|
1348
|
+
* type Dict = FromDictArray<[["foo", { foo: 1 }], ["bar", { bar: "hi" }]]>;
|
|
1349
|
+
* ```
|
|
1350
|
+
*/
|
|
1351
|
+
type FromDictArray<T extends [string, Record<string, unknown>][]> = ExpandRecursively<UnionToIntersection<T[number][1]>>;
|
|
1352
|
+
|
|
1353
|
+
/**
|
|
1354
|
+
* For a two-dimensional array, returns a _union type_ which combines the first element of the interior
|
|
1355
|
+
* array.
|
|
1356
|
+
*
|
|
1357
|
+
* ```ts
|
|
1358
|
+
* // 1 | 2
|
|
1359
|
+
* type F = SecondOfEach<[ ["foo", 1], ["bar", 2] ]>;
|
|
1360
|
+
* ```
|
|
1361
|
+
*/
|
|
1362
|
+
type SecondOfEach<T extends any[][]> = T[number][1] extends T[number][number] ? T[number][1] : never;
|
|
1363
|
+
|
|
1364
|
+
interface Array$1<T> {
|
|
1365
|
+
filter<U extends T>(pred: (a: T) => a is U): U[];
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
* Accepts a `DictArray` and a callback which receives each key
|
|
1369
|
+
* value pair.
|
|
1370
|
+
*/
|
|
1371
|
+
declare function filterDictArray<T extends object, C extends DictArrayFilterCallback<keyof T, T, true | false>>(dictArr: DictArray<T>, cb: C): DictArray<Omit<T, "">>;
|
|
1372
|
+
|
|
1373
|
+
/**
|
|
1374
|
+
* Build a key-value pair where both _key_ and _value_ are inferred. This
|
|
1375
|
+
* includes ensuring that the _key_ is a type literal not just a "string".
|
|
1376
|
+
*
|
|
1377
|
+
* > note: the value will be inferred but if you need to constrain it
|
|
1378
|
+
* > to a narrower type then both inferences will break and you should
|
|
1379
|
+
* > instead use `KV2` to get this capability.
|
|
1380
|
+
*/
|
|
1381
|
+
declare function kv<K extends string, N extends Narrowable, V extends Record<any, N> | boolean | number | string | null | undefined>(key: K, value: V): ExpandRecursively<Record<K, V>>;
|
|
1382
|
+
|
|
1383
|
+
/**
|
|
1384
|
+
* Converts an array of dictionaries with `key` and `value` properties to a singular dictionary.
|
|
1385
|
+
* ```ts
|
|
1386
|
+
* // { id: 123, foo: "bar" }
|
|
1387
|
+
* const arr = kvToDict([{ key: "id", value: 123 }, { key: "foo", value: "bar" }]);
|
|
1388
|
+
* ```
|
|
1389
|
+
*
|
|
1390
|
+
* Note: this is the inverse of `dictToKv()` function
|
|
1391
|
+
*/
|
|
1392
|
+
declare function kvToDict<K extends string, V extends Narrowable, T extends readonly Readonly<{
|
|
1393
|
+
key: K;
|
|
1394
|
+
value: V;
|
|
1395
|
+
}>[]>(kvArr: T): DictFromKv<T>;
|
|
1396
|
+
|
|
1397
|
+
/**
|
|
1398
|
+
* Type utility which converts `undefined[]` to `unknown[]`
|
|
1399
|
+
*/
|
|
1400
|
+
type UndefinedArrayIsUnknown<T extends any[]> = undefined[] extends T ? unknown[] : T;
|
|
1401
|
+
type AsArray<T, W extends boolean = false> = T extends any[] ? W extends true ? Widen<T> : T : W extends true ? UndefinedArrayIsUnknown<Widen<T>[]> : UndefinedArrayIsUnknown<T[]>;
|
|
1402
|
+
/**
|
|
1403
|
+
* Ensures that any input passed in is passed back as an array:
|
|
1404
|
+
*
|
|
1405
|
+
* - if it was already an array than this just serves as an _identity_ function
|
|
1406
|
+
* - if it was not then it wraps the element into a one element array of the
|
|
1407
|
+
* given type
|
|
1408
|
+
*
|
|
1409
|
+
* Note: by default the _type_ of values will be intentionally widened so that the value "abc"
|
|
1410
|
+
* is of type `string` not the literal `abc`. If you want to keep literal types then
|
|
1411
|
+
* change the optional _widen_ parameter to _false_.
|
|
1412
|
+
*/
|
|
1413
|
+
declare const asArray: <T extends Narrowable, W extends boolean = true>(thing: T, _widen?: W | undefined) => AsArray<T, W>;
|
|
1414
|
+
|
|
1415
|
+
/**
|
|
1416
|
+
* Groups an array of data based on the value of a property
|
|
1417
|
+
* in the objects within the array.
|
|
1418
|
+
* ```ts
|
|
1419
|
+
* const data = [ {}, {}, {} ];
|
|
1420
|
+
*
|
|
1421
|
+
* ```
|
|
1422
|
+
*
|
|
1423
|
+
* @ignore not implemented
|
|
1424
|
+
*/
|
|
1425
|
+
declare function groupBy<T extends Record<string, Narrowable>>(_data: Readonly<T[]>): void;
|
|
1426
|
+
|
|
1427
|
+
/**
|
|
1428
|
+
* The basic shape of a `Converter`
|
|
1429
|
+
*/
|
|
1430
|
+
type ConverterShape<S extends Narrowable, N extends Narrowable, B extends Narrowable, O extends Narrowable> = {
|
|
1431
|
+
string: <T extends string>(v: T) => S;
|
|
1432
|
+
number: <T extends number>(v: T) => N;
|
|
1433
|
+
boolean: <T extends boolean>(v: T) => B;
|
|
1434
|
+
object: <T extends Record<string, any>>(v: T) => O;
|
|
1435
|
+
};
|
|
1436
|
+
type ConverterKeys<S, N, B, O> = UnionToTuple<Keys<DictionaryWithoutValue<{
|
|
1437
|
+
string: S;
|
|
1438
|
+
number: N;
|
|
1439
|
+
boolean: B;
|
|
1440
|
+
object: O;
|
|
1441
|
+
}, undefined>>>;
|
|
1442
|
+
type ConverterInputType<T extends string> = T extends "string" ? string : T extends "number" ? number : T extends "boolean" ? boolean : T extends "object" ? Record<string, any> : unknown;
|
|
1443
|
+
type ConverterInputUnion<TConverted extends readonly any[], TRemaining extends readonly string[]> = [] extends TRemaining ? TConverted : ConverterInputUnion<[
|
|
1444
|
+
...TConverted,
|
|
1445
|
+
ConverterInputType<First<TRemaining>>
|
|
1446
|
+
], AfterFirst<TRemaining>>;
|
|
1447
|
+
/**
|
|
1448
|
+
* **AvailableConverters**
|
|
1449
|
+
*
|
|
1450
|
+
* Type utility which will produce the correct union type for a "converter"
|
|
1451
|
+
*/
|
|
1452
|
+
type AvailableConverters<S, N, B, O> = ConverterKeys<S, N, B, O> extends readonly string[] ? TupleToUnion<ConverterInputUnion<[], ConverterKeys<S, N, B, O>>> : never;
|
|
1453
|
+
|
|
1454
|
+
/**
|
|
1455
|
+
* **createConverter**(mapper)
|
|
1456
|
+
*
|
|
1457
|
+
* A runtime utility which allows for the creation of a function which
|
|
1458
|
+
* receives multiple wide types (string, number, boolean, object) and then transform it
|
|
1459
|
+
* based on the "wide type" but while retaining the potentially narrow values passed in.
|
|
1460
|
+
*
|
|
1461
|
+
* The number of wide types which the converter will accept is based on how it configured
|
|
1462
|
+
* as there are discrete functions which must be passed in for handling: strings, numbers,
|
|
1463
|
+
* booleans, and "objects" (aka, Record<string,any>).
|
|
1464
|
+
*
|
|
1465
|
+
* ```ts
|
|
1466
|
+
* // handles strings and numbers
|
|
1467
|
+
* const convert = createConverter({
|
|
1468
|
+
* string: s => `the string was ${s}`,
|
|
1469
|
+
* number: n => `the number was ${n}`,
|
|
1470
|
+
* });
|
|
1471
|
+
* ```
|
|
1472
|
+
*/
|
|
1473
|
+
declare function createConverter<S extends Narrowable = undefined, N extends Narrowable = undefined, B extends Narrowable = undefined, O extends Narrowable = undefined>(mapper: Partial<ConverterShape<S, N, B, O>>): <T extends AvailableConverters<S, N, B, O>>(input: T) => Widen<T> extends string ? S : Widen<Not<T, string>> extends number ? N : Widen<Not<Not<T, string>, number>> extends boolean ? B : Widen<Not<Not<Not<T, string>, number>, boolean>> extends {} ? O : unknown;
|
|
1474
|
+
|
|
1475
|
+
type ExplicitFunction<P extends any[], R extends any> = (...args: P) => R;
|
|
1476
|
+
/**
|
|
1477
|
+
* Takes a given function and converts it to an explicit representation
|
|
1478
|
+
* where the generics represent the _parameter_ and _return_ typings.
|
|
1479
|
+
*/
|
|
1480
|
+
declare function ExplicitFunction<T extends (...args: any[]) => any>(fn: T): ExplicitFunction<Parameters<T>, ReturnType<T>>;
|
|
1481
|
+
|
|
1482
|
+
/**
|
|
1483
|
+
* **UniqueDictionary**
|
|
1484
|
+
*
|
|
1485
|
+
* A dictionary converted by `arrayToObject()` which expects each key `S` to have a only a
|
|
1486
|
+
* single/unique value.
|
|
1487
|
+
*/
|
|
1488
|
+
type UniqueDictionary<S extends PropertyKey, N extends Narrowable, T extends Record<keyof T, N> & Record<S, any>> = {
|
|
1489
|
+
[V in T as V[S]]: V;
|
|
1490
|
+
};
|
|
1491
|
+
/**
|
|
1492
|
+
* **GeneralDictionary**
|
|
1493
|
+
*
|
|
1494
|
+
* A dictionary converted by `arrayToObject()` which expects each key `S` to have an
|
|
1495
|
+
* array of values.
|
|
1496
|
+
*/
|
|
1497
|
+
type GeneralDictionary<S extends PropertyKey, N extends Narrowable, T extends Record<keyof T, N> & Record<S, any>> = {
|
|
1498
|
+
[V in T as V[S]]: V[];
|
|
1499
|
+
};
|
|
1500
|
+
type ArrayConverter<S extends PropertyKey, U extends boolean> =
|
|
1501
|
+
/**
|
|
1502
|
+
* An `ArrayConverter` is the partial application of the `arrayToObject()`
|
|
1503
|
+
* utility. At this point, the configuration is setup already and all that's
|
|
1504
|
+
* left is to pass in an array of objects.
|
|
1505
|
+
*/
|
|
1506
|
+
<N extends Narrowable, T extends Record<keyof T, N> & Record<S, any>>(arr: readonly T[]) => true extends U ? UniqueDictionary<S, N, T> : GeneralDictionary<S, N, T>;
|
|
1507
|
+
/**
|
|
1508
|
+
* Converts an array of objects into a dictionary by picking a property name contained
|
|
1509
|
+
* by all objects and using that as the key to the dictionary.
|
|
1510
|
+
*
|
|
1511
|
+
* ```ts
|
|
1512
|
+
* const arr = [
|
|
1513
|
+
* { kind: "color", favorite: "blue", likes: 100 },
|
|
1514
|
+
* { kind: "song", favorite: "some song", likes: 25 }
|
|
1515
|
+
* ];
|
|
1516
|
+
* const dict = arrayToObject("kind")(arr);
|
|
1517
|
+
* ```
|
|
1518
|
+
*
|
|
1519
|
+
* This will produce a dictionary with keys of `color` and `song`.
|
|
1520
|
+
*/
|
|
1521
|
+
declare function arrayToObject<S extends PropertyKey, U extends boolean>(prop: S, unique?: U): ArrayConverter<S, true extends U ? true : false>;
|
|
1522
|
+
|
|
1523
|
+
declare function ifSameType<TValue extends Narrowable, TType extends string | number | boolean | object, IF extends Narrowable, ELSE extends Narrowable>(value: TValue, comparisonType: TType, ifExtends: <T extends TType & TValue>(v: T) => IF, doesNotExtend: (v: Not<TValue, TType>) => ELSE): Widen<TValue> extends Widen<TType> ? IF : ELSE;
|
|
1524
|
+
|
|
1525
|
+
declare function isArray<T>(i: T): IsArray<T>;
|
|
1526
|
+
/**
|
|
1527
|
+
* **ifArray**(T, IF, ELSE)
|
|
1528
|
+
*
|
|
1529
|
+
* A utility which evaluates a type `T` for whether it is an array and then
|
|
1530
|
+
*/
|
|
1531
|
+
declare function ifArray<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, isAnArray: <N extends T & readonly any[]>(arr: N) => IF, isNotAnArray: <N extends Exclude<T, any[]>>(nonArr: N) => ELSE): IfArray<T, IF, ELSE>;
|
|
1532
|
+
declare function ifArrayPartial<T extends Narrowable>(): <IF extends Narrowable, ELSE extends Narrowable>(isAnArray: <N extends T & readonly any[]>(arr: N) => IF, isNotAnArray: <N_1 extends Exclude<T, any[]>>(nonArr: N_1) => ELSE) => <V extends T>(val: V) => IfArray<V, IF, ELSE>;
|
|
1533
|
+
|
|
1534
|
+
/**
|
|
1535
|
+
* Runtime and type checks whether a variable is a boolean value.
|
|
1536
|
+
*/
|
|
1537
|
+
declare function isBoolean<T extends Narrowable>(i: T): IsBoolean<T>;
|
|
1538
|
+
/**
|
|
1539
|
+
* **ifBoolean**
|
|
1540
|
+
*
|
|
1541
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1542
|
+
* a _boolean_ and returns one of two values (strongly typed) based on the evaluation
|
|
1543
|
+
* of this criteria.
|
|
1544
|
+
*
|
|
1545
|
+
* @param val the value being tested
|
|
1546
|
+
* @param ifVal the value (strongly typed) returned if val is _boolean_
|
|
1547
|
+
* @param elseVal the value (strongly typed) returned if val is NOT a _boolean
|
|
1548
|
+
*/
|
|
1549
|
+
declare function ifBoolean<T, IF, ELSE>(val: T, ifVal: IF, elseVal: ELSE): IsBoolean<T> extends true ? IF : ELSE;
|
|
1550
|
+
|
|
1551
|
+
declare function isFalse<T>(i: T): IsFalse<T>;
|
|
1552
|
+
/**
|
|
1553
|
+
* **ifTrue**
|
|
1554
|
+
*
|
|
1555
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1556
|
+
* a _true_ and returns one of two values (strongly typed) based on the evaluation
|
|
1557
|
+
* of this criteria.
|
|
1558
|
+
*
|
|
1559
|
+
* @param val the value being tested
|
|
1560
|
+
* @param ifVal the value (strongly typed) returned if val is _true_ value
|
|
1561
|
+
* @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
|
|
1562
|
+
*
|
|
1563
|
+
* Note: at runtime there's no way to distinguish if the value was widely or loosely
|
|
1564
|
+
* typed so unlike the type utility there is no "MAYBE" state but if a wide type if
|
|
1565
|
+
* encountered the _type_ will the union of `IF` and `ELSE`.
|
|
1566
|
+
*/
|
|
1567
|
+
declare function ifFalse<T extends boolean, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IfFalse<T, IF, ELSE, IF | ELSE>;
|
|
1568
|
+
|
|
1569
|
+
type IsFunction<T> = T extends FunctionType ? true : false;
|
|
1570
|
+
type HybridFunction<TProps extends {}> = (<TArgs extends any[]>(...args: TArgs) => any) & TProps;
|
|
1571
|
+
type SimpleFunction = (...args: any[]) => any;
|
|
1572
|
+
type AnyFunction<TProps extends {} = {}> = SimpleFunction | HybridFunction<TProps>;
|
|
1573
|
+
/**
|
|
1574
|
+
* Checks whether a passed in value is a function and ensures run-time and types
|
|
1575
|
+
* are consistent.
|
|
1576
|
+
* ```ts
|
|
1577
|
+
* // true
|
|
1578
|
+
* const yup = isFunction(() => "hello world");
|
|
1579
|
+
* ```
|
|
1580
|
+
*
|
|
1581
|
+
* Note: the runtime `typeof [variable]` will correctly say "function" when a function is
|
|
1582
|
+
* encountered but if that function also has object types defined then the type will be a big
|
|
1583
|
+
* and ugly union type. This function will give you a proper boolean value in both cases.
|
|
1584
|
+
*/
|
|
1585
|
+
declare function isFunction<T>(input: T): IsFunction<T>;
|
|
1586
|
+
|
|
1587
|
+
type IsNull<T> = T extends null ? true : false;
|
|
1588
|
+
declare function isNull<T extends Narrowable>(i: T): T extends null ? true : false;
|
|
1589
|
+
/**
|
|
1590
|
+
* **ifNull**
|
|
1591
|
+
*
|
|
1592
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1593
|
+
* Null and returns one of two values (strongly typed) based on the evaluation
|
|
1594
|
+
* of this criteria.
|
|
1595
|
+
*
|
|
1596
|
+
* @param val the value being tested
|
|
1597
|
+
* @param ifVal the value (strongly typed) returned if val is `null`
|
|
1598
|
+
* @param elseVal the value (strongly typed) returned if val is NOT `null`
|
|
1599
|
+
*/
|
|
1600
|
+
declare function ifNull<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IsNull<T> extends true ? IF : ELSE;
|
|
1601
|
+
|
|
1602
|
+
type IsNumber<T> = T extends number ? true : false;
|
|
1603
|
+
declare function isNumber<T>(i: T): T extends number ? true : false;
|
|
1604
|
+
/**
|
|
1605
|
+
* **ifNumber**
|
|
1606
|
+
*
|
|
1607
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1608
|
+
* a _number_ and returns one of two values (strongly typed) based on the evaluation
|
|
1609
|
+
* of this criteria.
|
|
1610
|
+
*
|
|
1611
|
+
* @param val the value being tested
|
|
1612
|
+
* @param ifVal the value (strongly typed) returned if val is number
|
|
1613
|
+
* @param elseVal the value (strongly typed) returned if val is NOT a number
|
|
1614
|
+
*/
|
|
1615
|
+
declare function ifNumber<T, IF, ELSE>(val: T, ifVal: IF, elseVal: ELSE): IsNumber<T> extends true ? IF : ELSE;
|
|
1616
|
+
|
|
1617
|
+
type ObjectType = Not<Record<string, Narrowable>, FunctionType>;
|
|
1618
|
+
/**
|
|
1619
|
+
* Detects whether the passed in `v` is of type "object" where an object
|
|
1620
|
+
* is defined to be a string keyed dictionary style object. This means that
|
|
1621
|
+
* arrays are excluded, as well as functions which also have properties hanging
|
|
1622
|
+
* off of them.
|
|
1623
|
+
*/
|
|
1624
|
+
declare function isObject<T extends Narrowable>(i: T): IsObject<T>;
|
|
1625
|
+
declare function ifObject<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifObj: IF, notObj: ELSE): IfObject<T, IF, ELSE>;
|
|
1626
|
+
|
|
1627
|
+
/**
|
|
1628
|
+
* **IsString**
|
|
1629
|
+
*
|
|
1630
|
+
* Type utility which returns true/false based on whether `T` is a
|
|
1631
|
+
* string (wide or narrow).
|
|
1632
|
+
*/
|
|
1633
|
+
type IsString<T> = T extends string ? true : false;
|
|
1634
|
+
/**
|
|
1635
|
+
* **IfString**
|
|
1636
|
+
*
|
|
1637
|
+
* Type utility which determines if `T` is a _string_ (wide or narrow) and
|
|
1638
|
+
* returns `IF` type if it is, otherwise returns the type `ELSE`.
|
|
1639
|
+
*/
|
|
1640
|
+
type IfString<T extends Narrowable, //
|
|
1641
|
+
IF extends Narrowable, ELSE extends Narrowable> = IsString<T> extends true ? IF : IsString<T> extends false ? ELSE : IF | ELSE;
|
|
1642
|
+
|
|
1643
|
+
/**
|
|
1644
|
+
* **isString**
|
|
1645
|
+
*
|
|
1646
|
+
* Returns true or false on whether the passed in parameter is a
|
|
1647
|
+
* string (either a wide string or a string literal).
|
|
1648
|
+
*
|
|
1649
|
+
* The boolean return is traceable by the type system as well as the
|
|
1650
|
+
* runtime system.
|
|
1651
|
+
*/
|
|
1652
|
+
declare function isString<T>(i: T): IsString<T>;
|
|
1653
|
+
/**
|
|
1654
|
+
* **ifString**
|
|
1655
|
+
*
|
|
1656
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1657
|
+
* a _string_ and returns one of two values (strongly typed) based on the evaluation
|
|
1658
|
+
* of this criteria.
|
|
1659
|
+
*
|
|
1660
|
+
* @param val the value being tested for being a string
|
|
1661
|
+
* @param ifVal the value (strongly typed) returned if val is _string_
|
|
1662
|
+
* @param elseVal the value (strongly typed) returned if val is NOT a _string
|
|
1663
|
+
*/
|
|
1664
|
+
declare function ifString<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: <E extends string>(t: E & T) => IF, elseVal: ELSE): IfString<T, IF, ELSE>;
|
|
1665
|
+
|
|
1666
|
+
declare function isSymbol<T>(i: T): T extends symbol ? true : false;
|
|
1667
|
+
|
|
1668
|
+
/**
|
|
1669
|
+
* Run-time and type checking of whether a variable is `true`.
|
|
1670
|
+
*/
|
|
1671
|
+
declare function isTrue<T extends Narrowable>(i: T): IsTrue<T>;
|
|
1672
|
+
/**
|
|
1673
|
+
* **ifTrue**
|
|
1674
|
+
*
|
|
1675
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1676
|
+
* _true_.
|
|
1677
|
+
*
|
|
1678
|
+
* @param val the value being tested
|
|
1679
|
+
* @param ifVal the value (strongly typed) returned if val is _true_ value
|
|
1680
|
+
* @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
|
|
1681
|
+
*
|
|
1682
|
+
* Note: at runtime there's no way to distinguish if the value was widely or loosely
|
|
1683
|
+
* typed so unlike the type utility there is no "MAYBE" state but if a wide type if
|
|
1684
|
+
* encountered the _type_ will the union of `IF` and `ELSE`.
|
|
1685
|
+
*/
|
|
1686
|
+
declare function ifTrue<T extends boolean, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IfTrue<T, IF, ELSE, IF | ELSE>;
|
|
1687
|
+
|
|
1688
|
+
declare function isUndefined<T extends Narrowable>(i: T): undefined extends T ? true : false;
|
|
1689
|
+
/**
|
|
1690
|
+
* **ifUndefined**
|
|
1691
|
+
*
|
|
1692
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1693
|
+
* _undefined_ and returns one of two values (strongly typed) based on the evaluation
|
|
1694
|
+
* of this criteria.
|
|
1695
|
+
*
|
|
1696
|
+
* @param val the value being tested
|
|
1697
|
+
* @param ifVal the value (strongly typed) returned if val is `undefined`
|
|
1698
|
+
* @param elseVal the value (strongly typed) returned if val is NOT `undefined`
|
|
1699
|
+
*/
|
|
1700
|
+
declare function ifUndefined<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IsUndefined<T> extends true ? IF : ELSE;
|
|
1701
|
+
declare function ifDefined<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: <V extends Exclude<T, undefined>>(v: V) => IF, elseVal: ELSE): IsUndefined<T> extends true ? IF : ELSE;
|
|
1702
|
+
|
|
1703
|
+
interface Box<T> {
|
|
1704
|
+
__kind: "box";
|
|
1705
|
+
value: T;
|
|
1706
|
+
/**
|
|
1707
|
+
* Unbox the boxed value in the narrowest possible type.
|
|
1708
|
+
*
|
|
1709
|
+
* **note:** if the boxed value is a function with parameters you
|
|
1710
|
+
* can pass the parameters directly into the `b.unbox(params)` call.
|
|
1711
|
+
*/
|
|
1712
|
+
unbox: HasParameters<Box<T>["value"]> extends true ? Box<T>["value"] extends AnyFunction ? Box<T>["value"] extends (...args: infer A) => infer R ? <N extends A>(...args: N) => R : () => ReturnType<T> : () => T : () => T;
|
|
1713
|
+
}
|
|
1714
|
+
type BoxValue<T extends Box<any>> = T extends Box<infer V> ? V : never;
|
|
1715
|
+
type BoxedFnParams<T extends Box<any>> = T extends Box<infer V> ? V extends (...args: infer A) => any ? A : [] : [];
|
|
1716
|
+
type BoxedReturn<T extends Box<any>> = T extends Box<infer V> ? V extends Function ? ReturnType<T["value"]> : T["value"] : never;
|
|
1717
|
+
type NarrowBox<T> = <N extends BoxedFnParams<Box<T>> | First<BoxedFnParams<Box<T>>>>() => N extends BoxedFnParams<Box<T>> ? T extends (...args: any[]) => any ? (...args: N) => Box<T>["unbox"] : never : (first: N, ...rest: AfterFirst<BoxedFnParams<Box<T>>>) => BoxedReturn<Box<T>>;
|
|
1718
|
+
/**
|
|
1719
|
+
* Allows a value with an inner-type to be boxed into a dictionary
|
|
1720
|
+
* so that this type inference is preserved with the help of
|
|
1721
|
+
* [instantiation expressions](https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta/#instantiation-expressions).
|
|
1722
|
+
*
|
|
1723
|
+
* NOTE: this feature is immature at best right now
|
|
1724
|
+
*/
|
|
1725
|
+
declare function box<T extends Narrowable>(value: T): Box<T>;
|
|
1726
|
+
declare function isBox(thing: Narrowable): thing is Box<any>;
|
|
1727
|
+
/**
|
|
1728
|
+
* **boxDictionaryValues**(dict)
|
|
1729
|
+
*
|
|
1730
|
+
* Runtime utility which boxes each value in a dictionary
|
|
1731
|
+
*/
|
|
1732
|
+
declare function boxDictionaryValues<T extends {}>(dict: T): { [K in keyof T]: Box<T[K]>; };
|
|
1733
|
+
type Unbox<T> = T extends Box<infer U> ? U : T;
|
|
1734
|
+
/**
|
|
1735
|
+
* **unbox**(maybeBox)
|
|
1736
|
+
*
|
|
1737
|
+
* Unboxes a value if it was a box; otherwise it leaves _as is_.
|
|
1738
|
+
*/
|
|
1739
|
+
declare function unbox<T>(val: T): Unbox<T>;
|
|
1740
|
+
|
|
1741
|
+
/**
|
|
1742
|
+
* Build a _type_ from two run-time dictionaries.
|
|
1743
|
+
*
|
|
1744
|
+
* 1. The _first_ -- which is optional -- is interpreted as a _literal_ type definition
|
|
1745
|
+
* 2. The _second_ dictionary is interpreted as a "wide" definition of prop types
|
|
1746
|
+
*/
|
|
1747
|
+
declare function defineType<N extends Narrowable, TLiteral extends Record<string, N>>(literal?: TLiteral): <TWide extends object>(wide?: TWide) => ExpandRecursively<TWide & TLiteral>;
|
|
1748
|
+
|
|
1749
|
+
/**
|
|
1750
|
+
* An identity function for any type, with the goal of preserving literal type information
|
|
1751
|
+
* whereever possible.
|
|
1752
|
+
*/
|
|
1753
|
+
declare const identity: <N extends Narrowable, T extends string | number | boolean | symbol | Record<any, N> | null | undefined>(v: T) => T;
|
|
1754
|
+
|
|
1755
|
+
/**
|
|
1756
|
+
* Takes an object as input --which has an `id` property and returns it as the same
|
|
1757
|
+
* run-time content but with the _type_ of the `id` property being forced to a literal type
|
|
1758
|
+
*/
|
|
1759
|
+
declare function idLiteral<T extends {
|
|
1760
|
+
id: I;
|
|
1761
|
+
}, I extends PropertyKey>(o: T): T & {
|
|
1762
|
+
id: T["id"];
|
|
1763
|
+
};
|
|
1764
|
+
/**
|
|
1765
|
+
* Takes an object as input --which has an `name` property and returns it as the same
|
|
1766
|
+
* run-time content but with the _type_ of the `name` property being forced to a literal type
|
|
1767
|
+
*/
|
|
1768
|
+
declare function nameLiteral<T extends {
|
|
1769
|
+
name: I;
|
|
1770
|
+
}, I extends PropertyKey>(o: T): T & {
|
|
1771
|
+
name: T["name"];
|
|
1772
|
+
};
|
|
1773
|
+
/**
|
|
1774
|
+
* Takes an object as input --which has an `kind` property and returns it as the same
|
|
1775
|
+
* run-time content but with the _type_ of the `kind` property being forced to a literal type
|
|
1776
|
+
*/
|
|
1777
|
+
declare function kindLiteral<T extends {
|
|
1778
|
+
kind: I;
|
|
1779
|
+
}, I extends PropertyKey>(o: T): T & {
|
|
1780
|
+
kind: T["kind"];
|
|
1781
|
+
};
|
|
1782
|
+
declare function idTypeGuard<T extends {
|
|
1783
|
+
id: I;
|
|
1784
|
+
}, I extends PropertyKey>(_o: T): _o is T & {
|
|
1785
|
+
id: I;
|
|
1786
|
+
};
|
|
1787
|
+
/**
|
|
1788
|
+
* Takes an object as input and infers the narrow literal types of the property
|
|
1789
|
+
* values on the object.
|
|
1790
|
+
*
|
|
1791
|
+
* > Note: this addresses this [a known TS gap](https://github.com/microsoft/TypeScript/issues/30680).
|
|
1792
|
+
* > Hopefully at some point this will be addressed in the language.
|
|
1793
|
+
*/
|
|
1794
|
+
declare function literal<N extends Narrowable, T extends Record<keyof T, N>>(obj: T): T;
|
|
1795
|
+
|
|
1796
|
+
/**
|
|
1797
|
+
* **StripEnding**`<T, U>`
|
|
1798
|
+
*
|
|
1799
|
+
* Will strip off of `T` the ending defined by `U` when
|
|
1800
|
+
* both are string literals.
|
|
1801
|
+
* ```ts
|
|
1802
|
+
* type T = "Hello World";
|
|
1803
|
+
* type U = " World";
|
|
1804
|
+
* // "Hello"
|
|
1805
|
+
* type R = StripEnding<T,U>;
|
|
1806
|
+
* ```
|
|
1807
|
+
*/
|
|
1808
|
+
type StripTrailing<T extends string, U extends string> = IfLiteral<T, string extends U ? never : T extends `${infer Before}${U}` ? Before : T, string>;
|
|
1809
|
+
|
|
1810
|
+
/**
|
|
1811
|
+
* **stripTrailing**(content, strip)
|
|
1812
|
+
*
|
|
1813
|
+
* Runtime utility which ensures that last part of a string has substring
|
|
1814
|
+
* removed if it exists and that strong typing is preserved.
|
|
1815
|
+
*/
|
|
1816
|
+
declare function stripTrailing<T extends string, U extends string>(content: T, strip: U): StripTrailing<T, U>;
|
|
1817
|
+
|
|
1818
|
+
/**
|
|
1819
|
+
* **EnsureTrailing**`<T, U>`
|
|
1820
|
+
*
|
|
1821
|
+
* Will ensure that `T` ends with the substring `U` when
|
|
1822
|
+
* both are string literals.
|
|
1823
|
+
*
|
|
1824
|
+
* ```ts
|
|
1825
|
+
* type T = "Hello";
|
|
1826
|
+
* type U = " World";
|
|
1827
|
+
* // "Hello World"
|
|
1828
|
+
* type R = EnsureTrailing<T,U>;
|
|
1829
|
+
* ```
|
|
1830
|
+
*/
|
|
1831
|
+
type EnsureTrailing<T extends string, U extends string> = IfLiteral<T, string extends U ? never : T extends `${string}${U}` ? T : `${T}${U}`, string>;
|
|
1832
|
+
|
|
1833
|
+
/**
|
|
1834
|
+
* **ensureTrailing**(content, strip)
|
|
1835
|
+
*
|
|
1836
|
+
* Runtime utility which ensures that last part of a string -- `content` -- has the
|
|
1837
|
+
* substring `ensure` at the end and adds it if not present.
|
|
1838
|
+
*/
|
|
1839
|
+
declare function ensureTrailing<T extends string, U extends string>(content: T, ensure: U): EnsureTrailing<T, U>;
|
|
1840
|
+
|
|
1841
|
+
/**
|
|
1842
|
+
* Indicates whether `T` has _all_ uppercase characters in it.
|
|
1843
|
+
* ```ts
|
|
1844
|
+
* // true
|
|
1845
|
+
* type T = AllCaps<"FOOBAR">;
|
|
1846
|
+
* // false
|
|
1847
|
+
* type T = AllCaps<"FooBar">;
|
|
1848
|
+
* // "unknown"
|
|
1849
|
+
* type T = AllCaps<string>;
|
|
1850
|
+
* ```
|
|
1851
|
+
*/
|
|
1852
|
+
type AllCaps<T extends string> = string extends T ? "unknown" : T extends Uppercase<T> ? true : false;
|
|
1853
|
+
|
|
1854
|
+
/**
|
|
1855
|
+
* **Break<T,D>**
|
|
1856
|
+
*
|
|
1857
|
+
* Takes a string `T`, and splits it into a tuple of the form `[F, R]`.
|
|
1858
|
+
* ```ts
|
|
1859
|
+
* // ["the", " long and winding road"]
|
|
1860
|
+
* type T1 = Break<"the long and winding road", " ">;
|
|
1861
|
+
* // ["there", " I was, there I was"]
|
|
1862
|
+
* type T2 = Break<"there I was, there I was", " ">;
|
|
1863
|
+
* ```
|
|
1864
|
+
*/
|
|
1865
|
+
type Break<T extends string, D extends string> = (string extends T ? [string, string] : (T extends `${infer F}${D}${infer _R}` ? (F extends `${infer _X}${D}${infer _Y}` ? never : (T extends `${F}${infer R}` ? [F, R] : never)) : [T, ""]));
|
|
1866
|
+
|
|
1867
|
+
/**
|
|
1868
|
+
* Concatenates two arrays (of literals).
|
|
1869
|
+
* ```ts
|
|
1870
|
+
* // [ "foo", "bar", "baz" ]
|
|
1871
|
+
* type T = ArrConcat<["foo"], ["bar", "baz"]>;
|
|
1872
|
+
* ```
|
|
1873
|
+
*/
|
|
1874
|
+
type ArrConcat<A extends any[], B extends any[]> = [...A, ...B];
|
|
1875
|
+
|
|
1876
|
+
/**
|
|
1877
|
+
* Type utility which takes a string `S` and replaces the substring `W` with `P`.
|
|
1878
|
+
* ```ts
|
|
1879
|
+
* const fooy = "fooy";
|
|
1880
|
+
* // "Foo"
|
|
1881
|
+
* type Foo = Replace<typeof fooy, "y", "">;
|
|
1882
|
+
* ```
|
|
1883
|
+
*
|
|
1884
|
+
* Note: _the first match is replaced and all subsequent matches are ignored_
|
|
1885
|
+
*/
|
|
1886
|
+
type Replace<S extends string, W extends string, P extends string> = S extends "" ? "" : W extends "" ? S : S extends `${infer F}${W}${infer E}` ? `${F}${P}${E}` : S;
|
|
1887
|
+
|
|
1888
|
+
/**
|
|
1889
|
+
* Trims off whitespace on left of string
|
|
1890
|
+
* ```ts
|
|
1891
|
+
* // "foobar "
|
|
1892
|
+
* type T = TrimLeft<"\n\t foobar ">;
|
|
1893
|
+
* // string
|
|
1894
|
+
* type T = TrimLeft<string>;
|
|
1895
|
+
* ```
|
|
1896
|
+
*/
|
|
1897
|
+
type TrimLeft<S extends string> = string extends S ? string : S extends `${Whitespace}${infer Right}` ? TrimLeft<Right> : S;
|
|
1898
|
+
|
|
1899
|
+
/**
|
|
1900
|
+
* Provides the _left_ whitespace of a string
|
|
1901
|
+
* ```ts
|
|
1902
|
+
* // "\n\t "
|
|
1903
|
+
* type T = LeftWhitespace<"\n\t foobar">;
|
|
1904
|
+
* ```
|
|
1905
|
+
*/
|
|
1906
|
+
type LeftWhitespace<S extends string> = string extends S ? string : Replace<S, TrimLeft<S>, "">;
|
|
1907
|
+
|
|
1908
|
+
/**
|
|
1909
|
+
* Trims off whitespace on left of string
|
|
1910
|
+
* ```ts
|
|
1911
|
+
* // "\n foobar"
|
|
1912
|
+
* type T = TrimRight<"\n foobar \t">;
|
|
1913
|
+
* // string
|
|
1914
|
+
* type T = TrimRight<string>;
|
|
1915
|
+
* ```
|
|
1916
|
+
*/
|
|
1917
|
+
type TrimRight<S extends string> = string extends S ? string : S extends `${infer Right}${Whitespace}` ? TrimRight<Right> : S;
|
|
1918
|
+
|
|
1919
|
+
/**
|
|
1920
|
+
* Provides the _left_ whitespace of a string
|
|
1921
|
+
* ```ts
|
|
1922
|
+
* // "\n\t "
|
|
1923
|
+
* type T = LeftWhitespace<"\n\t foobar">;
|
|
1924
|
+
* ```
|
|
1925
|
+
*/
|
|
1926
|
+
type RightWhitespace<S extends string> = string extends S ? string : Replace<S, TrimRight<S>, "">;
|
|
1927
|
+
|
|
1928
|
+
/**
|
|
1929
|
+
* Type utility that provides the _length_ of a given string type in a way which
|
|
1930
|
+
* is _not_ limited to TS's recursive string length of roughly 48.
|
|
1931
|
+
*
|
|
1932
|
+
* ```ts
|
|
1933
|
+
* // 3
|
|
1934
|
+
* type Three = StringLength<"foo">;
|
|
1935
|
+
* ```
|
|
1936
|
+
*/
|
|
1937
|
+
type StringLength<S extends string, R extends number[] = []> = S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}${infer _Sixth}${infer _Sevebnth}${infer _Eighth}${infer _Ninth}${infer _Tenth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}${infer _Sixth}${infer _Sevebnth}${infer _Eighth}${infer _Ninth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}${infer _Sixth}${infer _Sevebnth}${infer _Eighth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}${infer _Sixth}${infer _Sevebnth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}${infer _Sixth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer Rest}` ? StringLength<Rest, [...R, 1, 1]> : S extends `${infer _First}${infer Rest}` ? StringLength<Rest, [...R, 1]> : [...R]["length"];
|
|
1938
|
+
|
|
1939
|
+
/**
|
|
1940
|
+
* Trims off blank spaces, `\n` and `\t` characters from both sides of a _string literal_.
|
|
1941
|
+
* ```ts
|
|
1942
|
+
* // "foobar"
|
|
1943
|
+
* type T = Trim<"\n\t foobar ">;
|
|
1944
|
+
* // string
|
|
1945
|
+
* type T = Trim<string>;
|
|
1946
|
+
* ```
|
|
1947
|
+
*/
|
|
1948
|
+
type Trim<S extends string> = string extends S ? string : S extends `${Whitespace}${infer Right}` ? Trim<Right> : S extends `${infer Left}${Whitespace}` ? Trim<Left> : S;
|
|
1949
|
+
|
|
1950
|
+
/**
|
|
1951
|
+
* An email address
|
|
1952
|
+
*/
|
|
1953
|
+
type Email = `${string}@${string}.${string}`;
|
|
1954
|
+
type Zip5 = `${NumericString}${NumericString}${string}${NumericString}`;
|
|
1955
|
+
type Zip4 = `${NumericString}${string}`;
|
|
1956
|
+
/**
|
|
1957
|
+
* A relatively strong type for Zip5 or Zip5+4 zip codes
|
|
1958
|
+
*/
|
|
1959
|
+
type ZipCode = Zip5 | `${Zip5}-${Zip4}`;
|
|
1960
|
+
|
|
1961
|
+
/**
|
|
1962
|
+
* If **ALL CAPS** it converts to all lowercase; if not then it does nothing */
|
|
1963
|
+
type LowerAllCaps<T extends string> = AllCaps<T> extends true ? Lowercase<T> : T;
|
|
1964
|
+
|
|
1965
|
+
type Delimiter = "_" | "-" | " ";
|
|
1966
|
+
/** convert all delimiters to dashes */
|
|
1967
|
+
type DashDelim<T extends string> = T extends `${infer Begin}${" "}${infer Rest}` ? DashDelim<`${Begin}-${Rest}`> : T extends `${infer Begin}${"_"}${infer Rest}` ? DashDelim<`${Begin}-${Rest}`> : T;
|
|
1968
|
+
/**
|
|
1969
|
+
* Converts a string literal type to a **PascalCase** representation.
|
|
1970
|
+
* ```ts
|
|
1971
|
+
* // "FooBar"
|
|
1972
|
+
* type T = PascalCase<"fooBar">;
|
|
1973
|
+
* type T = PascalCase<"foo-bar">;
|
|
1974
|
+
* type T = PascalCase<"foo_bar">;
|
|
1975
|
+
* type T = PascalCase<"\n foo_bar \t">;
|
|
1976
|
+
* ```
|
|
1977
|
+
*/
|
|
1978
|
+
type PascalCase<S extends string> = string extends S ? string : Trim<DashDelim<LowerAllCaps<S>>> extends `${infer Begin}${Delimiter}${infer Rest}` ? PascalCase<`${Capitalize<Begin>}${Capitalize<Rest>}`> : Capitalize<Trim<LowerAllCaps<S>>>;
|
|
1979
|
+
|
|
1980
|
+
type CamelCase<S extends string> = string extends S ? string : Uncapitalize<PascalCase<S>>;
|
|
1981
|
+
|
|
1982
|
+
/**
|
|
1983
|
+
* Capitalize all words in a string
|
|
1984
|
+
*/
|
|
1985
|
+
type CapitalizeWords<S extends string> = S extends `${infer L} ${infer R}` ? `${CapitalizeWords<L>} ${CapitalizeWords<R>}` : S extends `${infer L},${infer R}` ? `${CapitalizeWords<L>},${CapitalizeWords<R>}` : S extends `${infer L}.${infer R}` ? `${CapitalizeWords<L>}.${CapitalizeWords<R>}` : Capitalize<S>;
|
|
1986
|
+
|
|
1987
|
+
type DashToSnake<T extends string> = T extends `${infer HEAD}-${infer TAIL}` ? DashToSnake<`${HEAD}_${TAIL}`> : T;
|
|
1988
|
+
|
|
1989
|
+
/**
|
|
1990
|
+
* Indicates whether `T` has uppercase characters in it.
|
|
1991
|
+
* ```ts
|
|
1992
|
+
* // true
|
|
1993
|
+
* type T = HasUppercase<"Foobar">;
|
|
1994
|
+
* // false
|
|
1995
|
+
* type T = HasUppercase<"foobar">;
|
|
1996
|
+
* // "unknown"
|
|
1997
|
+
* type T = HasUppercase<string>;
|
|
1998
|
+
* ```
|
|
1999
|
+
*/
|
|
2000
|
+
type HasUppercase<T extends string> = string extends T ? "unknown" : T extends `${string}${UpperAlpha}${string}` ? true : false;
|
|
2001
|
+
|
|
2002
|
+
type _DU<T extends string> = T extends Lowercase<T> ? T : `-${Lowercase<T>}`;
|
|
2003
|
+
/**
|
|
2004
|
+
* Converts uppercase characters to a dash and then the lowercase equivalent
|
|
2005
|
+
* ```ts
|
|
2006
|
+
* // "one-two-three"
|
|
2007
|
+
* type T = DashUppercase<"oneTwoThree">;
|
|
2008
|
+
* ```
|
|
2009
|
+
*
|
|
2010
|
+
* _Intended to be used as a lower level utility; prefer `Dasherize<T>` for more full-fledged
|
|
2011
|
+
* dash solution_.
|
|
2012
|
+
*/
|
|
2013
|
+
type DashUppercase<T extends string> = HasUppercase<T> extends false ? T : T extends `${infer C0}${infer C1}${infer R}` ? `${_DU<C0>}${_DU<C1>}${DashUppercase<R>}` : T extends `${infer C0}${infer R}` ? `${_DU<C0>}${DashUppercase<R>}` : "";
|
|
2014
|
+
|
|
2015
|
+
type OneToOne = `1:1`;
|
|
2016
|
+
type OneToMany = `1:M`;
|
|
2017
|
+
type OneToZero = `1:0`;
|
|
2018
|
+
type ZeroToOne = `0:1`;
|
|
2019
|
+
type ZeroToMany = `0:M`;
|
|
2020
|
+
type ZeroToZero = `0:0`;
|
|
2021
|
+
type ManyToMany = "M:M";
|
|
2022
|
+
type ManyToOne = "M:1";
|
|
2023
|
+
type ManyToZero = "M:0";
|
|
2024
|
+
type CardinalityNode = "0" | "1" | "M";
|
|
2025
|
+
/**
|
|
2026
|
+
* Cardinality which expects a singular input and requires
|
|
2027
|
+
* 1 or many outputs.
|
|
2028
|
+
*
|
|
2029
|
+
* Note: choose `CardinalityFilter1` if you want to allow output
|
|
2030
|
+
* to have no outputs.
|
|
2031
|
+
*/
|
|
2032
|
+
type Cardinality1 = OneToOne | OneToMany;
|
|
2033
|
+
/**
|
|
2034
|
+
* Cardinality which expects a singular input and maps to 0,
|
|
2035
|
+
* 1, or many outputs.
|
|
2036
|
+
*/
|
|
2037
|
+
type CardinalityFilter1 = OneToOne | OneToMany | OneToZero;
|
|
2038
|
+
/**
|
|
2039
|
+
* Cardinality which expects a singular input which is allowed to be
|
|
2040
|
+
* _undefined_ or the expected type.
|
|
2041
|
+
*/
|
|
2042
|
+
type Cardinality0 = ZeroToOne | ZeroToMany | OneToOne | OneToMany;
|
|
2043
|
+
/**
|
|
2044
|
+
* Cardinality which expects a singular input -- which is allowed to be
|
|
2045
|
+
* _undefined_ -- and maps to 0,
|
|
2046
|
+
* 1, or many outputs.
|
|
2047
|
+
*/
|
|
2048
|
+
type CardinalityFilter0 = ZeroToOne | ZeroToMany | OneToOne | OneToMany | OneToZero | ZeroToZero;
|
|
2049
|
+
type CardinalityExplicit = `${number}:${number}`;
|
|
2050
|
+
/**
|
|
2051
|
+
* Cardinality of any sort between two types
|
|
2052
|
+
*/
|
|
2053
|
+
type Cardinality = CardinalityFilter0 | CardinalityFilter1 | ManyToMany | ManyToOne | ManyToZero | CardinalityExplicit;
|
|
2054
|
+
type CardinalityTuple<T extends Cardinality> = UnionToTuple<T>;
|
|
2055
|
+
/**
|
|
2056
|
+
* The first or _input_ part of the Cardinality relationship
|
|
2057
|
+
*/
|
|
2058
|
+
type CardinalityIn<T extends Cardinality> = T extends `${infer IN}:${string}` ? IN : never;
|
|
2059
|
+
/**
|
|
2060
|
+
* The second or _output_ part of the Cardinality relationship
|
|
2061
|
+
*/
|
|
2062
|
+
type CardinalityOut<T extends Cardinality> = T extends `${string}:${infer OUT}` ? OUT : never;
|
|
2063
|
+
type CardinalityInput<T, C extends Cardinality> = CardinalityTuple<C>[0] extends 0 ? T | undefined : CardinalityTuple<C>[0] extends 1 ? T : T[];
|
|
2064
|
+
|
|
2065
|
+
/**
|
|
2066
|
+
* Converts a string literal into a _dasherized_ format while ignoring _exterior_ whitespace.
|
|
2067
|
+
*
|
|
2068
|
+
* ```ts
|
|
2069
|
+
* // "foo-bar"
|
|
2070
|
+
* type Dash = Dasherize<"foo_bar">;
|
|
2071
|
+
* type Dash = Dasherize<"fooBar">;
|
|
2072
|
+
* type Dash = Dasherize<"FooBar">;
|
|
2073
|
+
* // "\n foo-bar \t"
|
|
2074
|
+
* type Dash = Dasherize<"\n foo bar \t">;
|
|
2075
|
+
* ```
|
|
2076
|
+
*/
|
|
2077
|
+
type Dasherize<S extends string> = string extends S ? string : DashUppercase<Trim<LowerAllCaps<S>>> extends `${infer Begin}${"_" | " "}${infer Rest}` ? Dasherize<`${Lowercase<Begin>}-${Rest}`> : Lowercase<DashUppercase<Uncapitalize<Trim<LowerAllCaps<S>>>>>;
|
|
2078
|
+
|
|
2079
|
+
/**
|
|
2080
|
+
* **EnsureLeading**`<T, U>`
|
|
2081
|
+
*
|
|
2082
|
+
* Will ensure that `T` ends with the _substring_ `U` when
|
|
2083
|
+
* both are string literals.
|
|
2084
|
+
*
|
|
2085
|
+
* ```ts
|
|
2086
|
+
* type T = " World";
|
|
2087
|
+
* type U = "Hello";
|
|
2088
|
+
* // "Hello World"
|
|
2089
|
+
* type R = EnsureLeading<T,U>;
|
|
2090
|
+
* ```
|
|
2091
|
+
*/
|
|
2092
|
+
type EnsureLeading<T extends string, U extends string> = IfLiteral<T, string extends U ? never : T extends `${U}${string}` ? T : `${U}${T}`, string>;
|
|
2093
|
+
|
|
2094
|
+
/**
|
|
2095
|
+
* Returns true or false value based on whether the string literal is capitalized.
|
|
2096
|
+
* ```ts
|
|
2097
|
+
* // true
|
|
2098
|
+
* type T2 = IsCapitalized<"One">;
|
|
2099
|
+
* // false
|
|
2100
|
+
* type T1 = IsCapitalized<"one">;
|
|
2101
|
+
* // "unknown"
|
|
2102
|
+
* const a: string = "Hi";
|
|
2103
|
+
* type T3 = IsCapitalized<typeof a>;
|
|
2104
|
+
* ```
|
|
2105
|
+
*
|
|
2106
|
+
* Note: _if the value passed in is a "string" then the result will be "unknown"_
|
|
2107
|
+
*/
|
|
2108
|
+
type IsCapitalized<T extends string> = string extends T ? "unknown" : T extends Capitalize<T> ? true : false;
|
|
2109
|
+
|
|
2110
|
+
/**
|
|
2111
|
+
* **KebabCase<T>** is an _alias_ for **Dasherize<T>**.
|
|
2112
|
+
* ```ts
|
|
2113
|
+
* // "foo-bar"
|
|
2114
|
+
* type Kebab = KebabCase<"foo_bar">;
|
|
2115
|
+
* type Kebab = KebabCase<"fooBar">;
|
|
2116
|
+
* type Kebab = KebabCase<"FooBar">;
|
|
2117
|
+
* // "\n foo-bar \t"
|
|
2118
|
+
* type Kebab = KebabCase<"\n foo bar \t">;
|
|
2119
|
+
* ``` */
|
|
2120
|
+
type KebabCase<T extends string> = Dasherize<T>;
|
|
2121
|
+
|
|
2122
|
+
/**
|
|
2123
|
+
* **StripStarting**`<T, U>`
|
|
2124
|
+
*
|
|
2125
|
+
* Will strip off of `T` the starting string defined by `U` when
|
|
2126
|
+
* both are string literals.
|
|
2127
|
+
* ```ts
|
|
2128
|
+
* type T = "Hello World";
|
|
2129
|
+
* type U = "Hello ";
|
|
2130
|
+
* // "World"
|
|
2131
|
+
* type R = StripStarting<T,U>;
|
|
2132
|
+
* ```
|
|
2133
|
+
*/
|
|
2134
|
+
type StripLeading<T extends string, U extends string> = IfLiteral<T, string extends U ? never : T extends `${U}${infer After}` ? After : T, string>;
|
|
2135
|
+
|
|
2136
|
+
/**
|
|
2137
|
+
* **PathJoin**`<T,U>`
|
|
2138
|
+
*
|
|
2139
|
+
* Type utility meant to bring 2 or more "path" strings together into
|
|
2140
|
+
* a valid "path". Where a "path" is represented as nothing more than
|
|
2141
|
+
* string characters delimited by a Posix `\` character.
|
|
2142
|
+
*
|
|
2143
|
+
* Note that the first part of the path will retain it's `\` if present
|
|
2144
|
+
* and the last one will preserve it's `\` character if present. You can
|
|
2145
|
+
* combine this utility with `EnsureTrailing<T>`, `StripTrailing<T>`,
|
|
2146
|
+
* `EnsureStarting<T>`, and `StripStarting<T>` to further shape
|
|
2147
|
+
* the type.
|
|
2148
|
+
*/
|
|
2149
|
+
type PathJoin<T extends string, U extends string | readonly string[]> = [] extends U ? T : U extends readonly string[] ? PathMultiJoin<PathJoin<T, "">, [...U]> : U extends string ? IfLiteral<T, IfLiteral<U, `${StripTrailing<T, "/">}/${StripLeading<U, "/">}`, `${StripTrailing<T, "/">}/${string}`>, IfLiteral<U, `${string}${U}`, string>> : never;
|
|
2150
|
+
type PathMultiJoin<TProcessed extends string, TRemaining extends readonly string[]> = [] extends TRemaining ? TProcessed : PathMultiJoin<PathJoin<TProcessed, First<TRemaining>>, AfterFirst<TRemaining>>;
|
|
2151
|
+
|
|
2152
|
+
type Consonant = "b" | "c" | "d" | "f" | "g" | "h" | "j" | "k" | "l" | "m" | "n" | "p" | "q" | "r" | "s" | "t" | "v" | "w" | "x" | "z" | "y";
|
|
2153
|
+
type Exceptions = "photo => photos" | "piano => pianos" | "halo => halos" | "foot => feet" | "man => men" | "woman => women" | "person => people" | "mouse => mice" | "series => series" | "sheep => sheep" | "money => monies" | "deer => deer";
|
|
2154
|
+
type SingularException<T = Exceptions> = T extends `${infer SINGULAR} => ${infer PLURAL}` ? SINGULAR : never;
|
|
2155
|
+
type PluralException<T extends SingularException, E extends Exceptions = Exceptions> = E extends `${T} => ${infer PLURAL}` ? PLURAL : never;
|
|
2156
|
+
type SingularNoun = "s" | "sh" | "ch" | "x" | "z" | "o";
|
|
2157
|
+
type F = "f" | "fe";
|
|
2158
|
+
type Y = `${Consonant}y`;
|
|
2159
|
+
type RemoveTrailingY<T> = T extends `${infer HEAD}y` ? HEAD : T;
|
|
2160
|
+
/** validates that a word ends with a pluralization exception */
|
|
2161
|
+
type isException<T extends string> = T extends SingularException ? T : never;
|
|
2162
|
+
/** validates that a string literal ends in "is" */
|
|
2163
|
+
type EndsIn_IS<T extends string> = T extends `${infer HEAD}is` ? T : never;
|
|
2164
|
+
/** validates that a string literal is a singular noun */
|
|
2165
|
+
type EndsInSingularNoun<T extends string> = T extends `${infer HEAD}${SingularNoun}` ? T : never;
|
|
2166
|
+
/** validates that a string literal ends in "f" or "fe" */
|
|
2167
|
+
type EndsIn_F<T extends string> = T extends `${infer HEAD}${F}` ? T : never;
|
|
2168
|
+
/** validates that a string literal ends a consonant followed by "y" */
|
|
2169
|
+
type EndsIn_Y<T extends string> = T extends `${infer HEAD}${Y}` ? T : never;
|
|
2170
|
+
/**
|
|
2171
|
+
* strings which end in the letters "is" should have an "es" added to the end
|
|
2172
|
+
*/
|
|
2173
|
+
type PluralizeEndingIn_IS<T extends string> = T extends `${infer HEAD}is` ? `${HEAD}ises` : T;
|
|
2174
|
+
/**
|
|
2175
|
+
* singular nouns should have "es" added to the end
|
|
2176
|
+
*/
|
|
2177
|
+
type PluralizeEndingSingularNoun<T extends string> = T extends `${infer HEAD}${SingularNoun}` ? `${T}es` : T;
|
|
2178
|
+
/**
|
|
2179
|
+
* strings which end in the letters "f" or "fe" should have "ves" replace the ending
|
|
2180
|
+
*/
|
|
2181
|
+
type PluralizeEnding_F<T extends string> = T extends `${infer HEAD}${F}` ? `${HEAD}ves` : T;
|
|
2182
|
+
/**
|
|
2183
|
+
* singular nouns should have "es" added to the end
|
|
2184
|
+
*/
|
|
2185
|
+
type PluralizeEndingIn_Y<T extends string> = T extends `${infer HEAD}${Y}` ? `${RemoveTrailingY<T>}ies` : T;
|
|
2186
|
+
type Pluralize<T extends string> = T extends isException<T> ? PluralException<T> : T extends EndsIn_IS<T> ? PluralizeEndingIn_IS<T> : T extends EndsInSingularNoun<T> ? PluralizeEndingSingularNoun<T> : T extends EndsIn_F<T> ? PluralizeEnding_F<T> : T extends EndsIn_Y<T> ? PluralizeEndingIn_Y<T> : `${T}s`;
|
|
2187
|
+
|
|
2188
|
+
/** convert space to dash */
|
|
2189
|
+
type SpaceToDash<T extends string> = T extends `${infer Begin}${" "}${infer Rest}` ? SpaceToDash<`${Begin}-${Rest}`> : T;
|
|
2190
|
+
/**
|
|
2191
|
+
* Converts a string literal type to _snake_case_.
|
|
2192
|
+
* ```ts
|
|
2193
|
+
* // "foo_bar"
|
|
2194
|
+
* type T = SnakeCase<"fooBar">;
|
|
2195
|
+
* type T = SnakeCase<"FooBar">;
|
|
2196
|
+
* type T = SnakeCase<"foo-bar">;
|
|
2197
|
+
* type T = SnakeCase<"\n foo bar \t">;
|
|
2198
|
+
* ``` */
|
|
2199
|
+
type SnakeCase<S extends string> = string extends S ? string : DashUppercase<Uncapitalize<SpaceToDash<Trim<LowerAllCaps<S>>>>> extends `${infer Begin}${"-"}${infer Rest}` ? SnakeCase<`${Lowercase<Begin>}_${Rest}`> : Lowercase<DashUppercase<Uncapitalize<Trim<LowerAllCaps<S>>>>>;
|
|
2200
|
+
|
|
2201
|
+
type NetworkProtocol = "http" | "https" | "file" | "ws" | "wss";
|
|
2202
|
+
/**
|
|
2203
|
+
* A literal variant of _string_ which is meant to represent a domain name
|
|
2204
|
+
* (e.g., `www.someplace.com`, etc.)
|
|
2205
|
+
*/
|
|
2206
|
+
type DomainName = `${AlphaNumeric}${string}.${AlphaNumeric}${string}` | `${AlphaNumeric}${string}.${AlphaNumeric}${string}.${string}` | `${AlphaNumeric}${string}.${AlphaNumeric}${string}.${string}.${string}`;
|
|
2207
|
+
type RelativeUrl = `${VariableName | "/"}`;
|
|
2208
|
+
/**
|
|
2209
|
+
* A literal variant of _string_ which forces a string to follow conventions
|
|
2210
|
+
* for a fully qualified URL like `https://google.com`. It can't ensure the
|
|
2211
|
+
* type is fully valid but does help to avoid some typos.
|
|
2212
|
+
*/
|
|
2213
|
+
type FullyQualifiedUrl = `${NetworkProtocol}://${Ipv4 | DomainName}/${string}`;
|
|
2214
|
+
type UrlBuilder = (<P extends NetworkProtocol, D extends DomainName, B extends RelativeUrl>(protocol: P, domain: D, basePath: B) => `${P}://${D}/${B}`) | (<U extends RelativeUrl>(url: U) => U);
|
|
2215
|
+
|
|
2216
|
+
/**
|
|
2217
|
+
* **ensureLeading**(content, strip)
|
|
2218
|
+
*
|
|
2219
|
+
* Runtime utility which ensures that last part of a string -- `content` -- has the
|
|
2220
|
+
* substring `ensure` at the end and adds it if not present.
|
|
2221
|
+
*/
|
|
2222
|
+
declare function ensureLeading<T extends string, U extends string>(content: T, ensure: U): EnsureLeading<T, U>;
|
|
2223
|
+
|
|
2224
|
+
/**
|
|
2225
|
+
* **pathJoin**`<T,U>(begin, ...rest)`
|
|
2226
|
+
*
|
|
2227
|
+
* Run time utility which joins two strings together with
|
|
2228
|
+
* the intent to have them be divided by a Posix `/` character
|
|
2229
|
+
* appropriate for Unix file paths and URLs.
|
|
2230
|
+
*
|
|
2231
|
+
* **note:** to support more than two paths being joined there
|
|
2232
|
+
* is now the ability to add a tuple of paths into the _rest_
|
|
2233
|
+
* parameter
|
|
2234
|
+
*/
|
|
2235
|
+
declare function pathJoin<T extends string, U extends readonly string[]>(begin: T, ...rest: U): PathJoin<T, U>;
|
|
2236
|
+
|
|
2237
|
+
/**
|
|
2238
|
+
* **Suggest**
|
|
2239
|
+
*
|
|
2240
|
+
* Type utility that helps to build a enumerated set
|
|
2241
|
+
* of string literals which _could_ be the value for
|
|
2242
|
+
* a string based property but _allows_ a string that
|
|
2243
|
+
* is not part of the suggestion to be typed in too.
|
|
2244
|
+
*/
|
|
2245
|
+
type Suggest<T extends string> = T | (string & {});
|
|
2246
|
+
/**
|
|
2247
|
+
* **SuggestNumeric**`<T>`
|
|
2248
|
+
*
|
|
2249
|
+
* Type utility that helps to build a enumerated set
|
|
2250
|
+
* of numeric literals which _could_ be the value for
|
|
2251
|
+
* a number based property but _allows_ a number that
|
|
2252
|
+
* is not part of the suggestion to be typed in too.
|
|
2253
|
+
*/
|
|
2254
|
+
type SuggestNumeric<T extends number> = T | (number & {});
|
|
2255
|
+
|
|
2256
|
+
/**
|
|
2257
|
+
* **wide**
|
|
2258
|
+
*
|
|
2259
|
+
* Provides a dictionary of _wide_ types
|
|
2260
|
+
*/
|
|
2261
|
+
declare const wide: {
|
|
2262
|
+
readonly boolean: boolean;
|
|
2263
|
+
readonly string: string;
|
|
2264
|
+
readonly number: number;
|
|
2265
|
+
readonly symbol: Symbol;
|
|
2266
|
+
readonly null: null;
|
|
2267
|
+
readonly undefined: undefined;
|
|
2268
|
+
};
|
|
2269
|
+
|
|
2270
|
+
type Condition<TInput extends Narrowable, TResult extends boolean> = (input: TInput) => TResult;
|
|
2271
|
+
declare const condition: <TInput extends Narrowable, C extends Condition<Narrowable, boolean>>(c: C, input: TInput) => boolean;
|
|
2272
|
+
|
|
2273
|
+
/**
|
|
2274
|
+
* **TypeGuard**
|
|
2275
|
+
*
|
|
2276
|
+
* a typing for a **TS** type-guard which evaluates an _unknown_ input
|
|
2277
|
+
* and determines if it is of type `T`.
|
|
2278
|
+
*/
|
|
2279
|
+
type TypeGuard<T> = (thing: unknown) => thing is T;
|
|
2280
|
+
|
|
2281
|
+
type Type<T extends any, V extends Function> = {
|
|
2282
|
+
name: string;
|
|
2283
|
+
type: T;
|
|
2284
|
+
typeGuard: TypeGuard<T>;
|
|
2285
|
+
is: V;
|
|
2286
|
+
};
|
|
2287
|
+
declare const typeApi: () => {
|
|
2288
|
+
readonly string: Type<string, typeof isString>;
|
|
2289
|
+
readonly boolean: Type<boolean, typeof isBoolean>;
|
|
2290
|
+
readonly number: Type<number, typeof isNumber>;
|
|
2291
|
+
readonly function: Type<Function | (Function & {
|
|
2292
|
+
[key: string]: any;
|
|
2293
|
+
}), typeof isFunction>;
|
|
2294
|
+
readonly null: Type<null, typeof isNull>;
|
|
2295
|
+
readonly symbol: Type<symbol, typeof isSymbol>;
|
|
2296
|
+
readonly undefined: Type<undefined, typeof isUndefined>;
|
|
2297
|
+
readonly true: Type<true, typeof isTrue>;
|
|
2298
|
+
readonly false: Type<false, typeof isFalse>;
|
|
2299
|
+
readonly object: Type<Record<string, Narrowable>, typeof isObject>;
|
|
2300
|
+
readonly array: Type<any[], typeof isArray>;
|
|
2301
|
+
};
|
|
2302
|
+
type TypeApi = ReturnType<typeof typeApi>;
|
|
2303
|
+
declare function isType<T extends any, V extends Function>(t: unknown): t is Type<T, V>;
|
|
2304
|
+
type TypeDefinition<T extends any, V extends Function> = (defn: TypeApi) => Type<T, V>;
|
|
2305
|
+
declare function type<T extends any, V extends Function>(fn: TypeDefinition<T, V>): Type<T, V>;
|
|
2306
|
+
|
|
2307
|
+
/**
|
|
2308
|
+
* **withValue**
|
|
2309
|
+
*
|
|
2310
|
+
* Reduces a dictionary object -- in both _type_ and _run-time_ structure -- to only those
|
|
2311
|
+
* key/value pairs which have a specified value. For instance:
|
|
2312
|
+
*
|
|
2313
|
+
* ```ts
|
|
2314
|
+
* const obj = { foo: 1, bar: 2, message: "hi there" };
|
|
2315
|
+
* // { message: "hi there" }
|
|
2316
|
+
* const onlyStrings = withValue(t => t.string)(obj);
|
|
2317
|
+
* // { foo: 1 }
|
|
2318
|
+
* const justOne = withValue(t => t.literal(1))(obj);
|
|
2319
|
+
* ```
|
|
2320
|
+
*
|
|
2321
|
+
* Note: _often useful to provide run-time type profiles with the_ `inferredType` _utility_
|
|
2322
|
+
*/
|
|
2323
|
+
declare function withValue<T extends any, V extends Function>(td: TypeDefinition<T, V>): <N extends Narrowable, R extends Record<string, N>>(obj: R) => ExpandRecursively<Pick<R, KeysWithValue<T, R>>>;
|
|
2324
|
+
|
|
2325
|
+
type Omit$1<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
|
2326
|
+
interface IConfigurator<C = {}> {
|
|
2327
|
+
set<V, K extends string, KV = {
|
|
2328
|
+
[U in K]: V;
|
|
2329
|
+
}>(key: K, value: V): asserts this is IConfigurator<ExpandRecursively<C & KV>>;
|
|
2330
|
+
remove<K extends string & keyof C>(key: K): asserts this is IConfigurator<ExpandRecursively<Omit$1<C, K>>>;
|
|
2331
|
+
done(): C;
|
|
2332
|
+
}
|
|
2333
|
+
/**
|
|
2334
|
+
* **Configurator**
|
|
2335
|
+
*
|
|
2336
|
+
* This function provides a configurator which uses TypeScript assertions
|
|
2337
|
+
* to narrow the scope of variables. Using type assertions though means we
|
|
2338
|
+
* can't also return values and therefore a _fluent_ API style is not possible.
|
|
2339
|
+
*
|
|
2340
|
+
* Note: this approach does require, that you explicitly use the `IConfigurator`
|
|
2341
|
+
* interface exported by this library. Without it you'd getting annoying TS errors
|
|
2342
|
+
* on every call to `set()` but adding it is simple enough:
|
|
2343
|
+
*
|
|
2344
|
+
* ```ts
|
|
2345
|
+
* import { Configurator, IConfigurator } from "inferred-types";
|
|
2346
|
+
* const config: IConfigurator = Configurator();
|
|
2347
|
+
* ```
|
|
2348
|
+
*
|
|
2349
|
+
* If you want to specify some guideline params which you expect to be set, you
|
|
2350
|
+
* can add them like so:
|
|
2351
|
+
*
|
|
2352
|
+
* ```ts
|
|
2353
|
+
* export type IExpected = { foo: number, bar: string };
|
|
2354
|
+
* const config: IConfigurator<IExpected> = Configurator<IExpected>();
|
|
2355
|
+
* ```
|
|
2356
|
+
*
|
|
2357
|
+
* This configuration will ensure that `foo` and `bar` will be seen as optional
|
|
2358
|
+
* parameters. If you set them they will stop being optional.
|
|
2359
|
+
*/
|
|
2360
|
+
declare function Configurator(): IConfigurator<{}>;
|
|
2361
|
+
|
|
2362
|
+
interface IFluentConfigurator<C> {
|
|
2363
|
+
/**
|
|
2364
|
+
* **set**
|
|
2365
|
+
*
|
|
2366
|
+
* Sets a new key/value pair to the configurator.
|
|
2367
|
+
*
|
|
2368
|
+
* @param key the key to put this new configuration item
|
|
2369
|
+
* @param value the value of the configuration item
|
|
2370
|
+
*/
|
|
2371
|
+
set<V, K extends string, KV = {
|
|
2372
|
+
[U in K]: V;
|
|
2373
|
+
}>(key: K, value: V): IFluentConfigurator<C & KV>;
|
|
2374
|
+
done(): ExpandRecursively<C>;
|
|
2375
|
+
}
|
|
2376
|
+
/**
|
|
2377
|
+
* This function will return a basic _configurator_ API surface which allows
|
|
2378
|
+
* you to add name/value pairs to a growing dictionary of strongly typed data.
|
|
2379
|
+
*
|
|
2380
|
+
* When configuration is complete, you call the `done()` endpoint and the typed
|
|
2381
|
+
* configuration will be returned with the API removed.
|
|
2382
|
+
*
|
|
2383
|
+
* > **Note:** the approach taken here requires that you configure using a **fluent style**
|
|
2384
|
+
* exclusively. If you don't the non-fluent properties set will not show up
|
|
2385
|
+
* in the typing or the run-time object.
|
|
2386
|
+
*/
|
|
2387
|
+
declare function FluentConfigurator<I>(initial?: I): IFluentConfigurator<{}>;
|
|
2388
|
+
|
|
2389
|
+
type Widen<T> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : T extends readonly string[] ? string[] : T extends readonly number[] ? number[] : T extends readonly boolean[] ? boolean[] : T extends readonly AnyFunction[] ? AnyFunction[] : T extends readonly any[] ? TupleToUnion<T>[] : T extends {} ? {} : T;
|
|
2390
|
+
|
|
2391
|
+
/**
|
|
2392
|
+
* **Includes**`<TSource, TValue>`
|
|
2393
|
+
*
|
|
2394
|
+
* Type utility which returns `true` or `false` based on whether `TValue` is found
|
|
2395
|
+
* in `TSource`. Where `TSource` can be a string literal or an array of string literals.
|
|
2396
|
+
*
|
|
2397
|
+
* **Note:** if the source is a _wide_ type (aka, `string` or `string[]`) then there is
|
|
2398
|
+
* no way to know at design-time whether the value includes `TValue` and so it will return
|
|
2399
|
+
* a type of `boolean`.
|
|
2400
|
+
*/
|
|
2401
|
+
type Includes<TSource extends string | readonly string[], TValue extends string> = TSource extends string[] ? IsStringLiteral<TupleToUnion<TSource>> extends true ? IsLiteral<TValue> extends true ? TValue extends TupleToUnion<TSource> ? true : false : boolean : boolean : TSource extends string ? IsLiteral<TSource> extends true ? IsLiteral<TValue> extends true ? TSource extends `${string}${TValue}${string}` ? true : false : boolean : boolean : boolean;
|
|
2402
|
+
|
|
2403
|
+
type IsScalar<T extends Narrowable> = [T] extends [string] ? true : [T] extends [number] ? true : [T] extends [boolean] ? true : false;
|
|
2404
|
+
/**
|
|
2405
|
+
* **IfScalar**`<T, IF, ELSE>`
|
|
2406
|
+
*
|
|
2407
|
+
* Branch type utility which returns `IF` when `T` is a scalar value (aka, string, number, or boolean) and `ELSE` otherwise
|
|
2408
|
+
*/
|
|
2409
|
+
type IfScalar<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable> = IsScalar<T> extends true ? IF : ELSE;
|
|
2410
|
+
|
|
2411
|
+
/**
|
|
2412
|
+
* **HasParameters**`<T>`
|
|
2413
|
+
*
|
|
2414
|
+
* Type utility which detects if `T` is both a function and whether that
|
|
2415
|
+
* function has at least one type parameter.
|
|
2416
|
+
* ```ts
|
|
2417
|
+
* const fn = (foo: string) => `${foo}bar`;
|
|
2418
|
+
* // true
|
|
2419
|
+
* type P = HasParameters<typeof fn>;
|
|
2420
|
+
* ```
|
|
2421
|
+
*/
|
|
2422
|
+
type HasParameters<T extends Narrowable> = T extends AnyFunction ? IsEqual<Length<Parameters<T>>, 0> extends true ? false : true : false;
|
|
2423
|
+
|
|
2424
|
+
/**
|
|
2425
|
+
* **IsObject**
|
|
2426
|
+
*
|
|
2427
|
+
* Boolean type utility used to check whether a type `T` is an object
|
|
2428
|
+
*/
|
|
2429
|
+
type IsObject<T> = Mutable<T> extends Record<string, any> ? T extends FunctionType ? false : Mutable<T> extends any[] ? false : true : false;
|
|
2430
|
+
/**
|
|
2431
|
+
* **IfObject**
|
|
2432
|
+
*
|
|
2433
|
+
* Branch type utility with return `IF` when `T` extends an object type
|
|
2434
|
+
* and `ELSE` otherwise
|
|
2435
|
+
*/
|
|
2436
|
+
type IfObject<T, IF extends Narrowable, ELSE extends Narrowable> = IsObject<T> extends true ? IF : ELSE;
|
|
2437
|
+
|
|
2438
|
+
/**
|
|
2439
|
+
* **StartsWith**<TValue, TStartsWith>
|
|
2440
|
+
*
|
|
2441
|
+
* A type utility which checks whether `T` _starts with_ the string literal `U`.
|
|
2442
|
+
*
|
|
2443
|
+
* If both `T` and `U` are string literals then the type system will resolve
|
|
2444
|
+
* to a literal `true` or `false` but if either is not a literal that it will
|
|
2445
|
+
* just resolve to `boolean` as the value can not be known at design time..
|
|
2446
|
+
*/
|
|
2447
|
+
type StartsWith<TValue extends string, TStartsWith extends string> = IsStringLiteral<TStartsWith> extends true ? IsStringLiteral<TValue> extends true ? TValue extends `${TStartsWith}${string}` ? true : false : boolean : boolean;
|
|
2448
|
+
/**
|
|
2449
|
+
* **IfStartsWith**<TValue, TStartsWith, IF, ELSE, MAYBE>
|
|
2450
|
+
*
|
|
2451
|
+
* Type utility which converts type to `IF` type _if_ TValue _starts with_ `TStartsWith` but
|
|
2452
|
+
* otherwise converts type to `ELSE`.
|
|
2453
|
+
*
|
|
2454
|
+
* Note, that there is also an optional `MAYBE` type
|
|
2455
|
+
* which can be stated for cases where TValue or TStartsWith _might_ be the wider `string`
|
|
2456
|
+
* type and therefore the type is unknown at design time.
|
|
2457
|
+
*/
|
|
2458
|
+
type IfStartsWith<TValue extends string, TStartsWith extends string, IF extends Narrowable, ELSE extends Narrowable> = StartsWith<TValue, TStartsWith> extends true ? IF : StartsWith<TValue, TStartsWith> extends false ? ELSE : IF | ELSE;
|
|
2459
|
+
|
|
2460
|
+
/**
|
|
2461
|
+
* **EndsWith**<T,U>
|
|
2462
|
+
*
|
|
2463
|
+
* A type utility which checks whether `T` _ends with_ the string literal `U`.
|
|
2464
|
+
*
|
|
2465
|
+
* If both `T` and `U` are string literals then the type system will resolve
|
|
2466
|
+
* to a literal `true` or `false` but if either is not a literal that it will
|
|
2467
|
+
* just resolve to `boolean` as the value can not be known at design time..
|
|
2468
|
+
*/
|
|
2469
|
+
type EndsWith<TValue extends string, TEndsWith extends string> = IsStringLiteral<TEndsWith> extends true ? IsStringLiteral<TValue> extends true ? TValue extends `${string}${TEndsWith}` ? true : false : boolean : boolean;
|
|
2470
|
+
/**
|
|
2471
|
+
* **IfEndsWith**<TValue, TEndsWith, IF, ELSE, MAYBE>
|
|
2472
|
+
*
|
|
2473
|
+
* Type utility which converts type to `IF` type _if_ `TValue` _ends with_ `TEndsWith` but
|
|
2474
|
+
* otherwise converts type to `ELSE`. If there are wide types in the mix then the type will
|
|
2475
|
+
* result in the union of IF and ELSE.
|
|
2476
|
+
*/
|
|
2477
|
+
type IfEndsWith<TValue extends string, TEndsWith extends string, IF extends Narrowable, ELSE extends Narrowable> = EndsWith<TValue, TEndsWith> extends true ? IF : EndsWith<TValue, TEndsWith> extends false ? ELSE : IF | ELSE;
|
|
2478
|
+
|
|
2479
|
+
/**
|
|
2480
|
+
* Makes a readonly structure mutable
|
|
2481
|
+
*/
|
|
2482
|
+
type Mutable<T> = {
|
|
2483
|
+
-readonly [K in keyof T]: IsObject<T[K]> extends true ? Mutable<T[K]> : T[K];
|
|
2484
|
+
};
|
|
2485
|
+
|
|
2486
|
+
/**
|
|
2487
|
+
* Provides a negation of a type of the type `T` _not_ `U`.
|
|
2488
|
+
* ```ts
|
|
2489
|
+
* const foo = 42;
|
|
2490
|
+
* // 33
|
|
2491
|
+
* type NotTheMeaningOfLife = Not<33, 42>;
|
|
2492
|
+
* // never
|
|
2493
|
+
* type NotTheMeaningOfLife = Not<42, 42>;
|
|
2494
|
+
* ```
|
|
2495
|
+
*
|
|
2496
|
+
* Note: same as `Exclude`
|
|
2497
|
+
*/
|
|
2498
|
+
type Not<T, U> = T extends U ? never : T;
|
|
2499
|
+
|
|
2500
|
+
type Digital = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
|
2501
|
+
type MakeArray<S extends string, T extends any[] = []> = S extends `${T["length"]}` ? T : MakeArray<S, [...T, 0]>;
|
|
2502
|
+
type Multiply10<T extends any[]> = [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T];
|
|
2503
|
+
/**
|
|
2504
|
+
* Converts a string literal to a numeric literal
|
|
2505
|
+
* ```ts
|
|
2506
|
+
* // 0
|
|
2507
|
+
* type Zero = Numeric<"0">;
|
|
2508
|
+
* // 10
|
|
2509
|
+
* type Ten = Numeric<"10">;
|
|
2510
|
+
* ```
|
|
2511
|
+
*/
|
|
2512
|
+
type Numeric<S extends string, T extends any[] = []> = S extends `${infer S1}${infer S2}` ? S1 extends Digital ? Numeric<S2, [...Multiply10<T>, ...MakeArray<S1>]> : never : T["length"];
|
|
2513
|
+
|
|
2514
|
+
/**
|
|
2515
|
+
* **Opaque**
|
|
2516
|
+
*
|
|
2517
|
+
* Create an opaque type, which hides its internal details from the public, and
|
|
2518
|
+
* can only be created by being used explicitly.
|
|
2519
|
+
*
|
|
2520
|
+
* Note: taken from [type-fest](https://github.com/sindresorhus/type-fest/blob/main/source/opaque.d.ts)
|
|
2521
|
+
* repo.
|
|
2522
|
+
*/
|
|
2523
|
+
type Opaque<Type, Token = unknown> = Type & {
|
|
2524
|
+
readonly __opaque__: Token;
|
|
2525
|
+
};
|
|
2526
|
+
|
|
2527
|
+
/**
|
|
2528
|
+
* **Retain<T, K>**
|
|
2529
|
+
*
|
|
2530
|
+
* Reduces the type system to just the key/values which are represented in `K`.
|
|
2531
|
+
* The `L` generic can largely be ignored unless you need _literal_ equality.
|
|
2532
|
+
*
|
|
2533
|
+
* ```ts
|
|
2534
|
+
* type Obj = { foo: 1, bar: number, baz: string };
|
|
2535
|
+
* // { foo: 1, bar: number }
|
|
2536
|
+
* type Retained = Retain<Obj, "foo" | "bar">;
|
|
2537
|
+
* ```
|
|
2538
|
+
*
|
|
2539
|
+
* **Note:** in essence this is the _opposite_ of `Exclude<T,K>`
|
|
2540
|
+
*/
|
|
2541
|
+
type Retain<T, K extends keyof T> = Pick<T, Include<keyof T, K>>;
|
|
2542
|
+
|
|
2543
|
+
/**
|
|
2544
|
+
* Allows filtering down `T` to those which extend a given type `U`.
|
|
2545
|
+
*
|
|
2546
|
+
* - `T` is either a dictionary (where keys will be used to compare) or
|
|
2547
|
+
* a readonly sting array.
|
|
2548
|
+
* ```ts
|
|
2549
|
+
* const arr = ["foo", "bar", "baz"];
|
|
2550
|
+
* // "bar" | "baz"
|
|
2551
|
+
* type BA = Where<typeof arr, `ba${string}`>;
|
|
2552
|
+
* ```
|
|
2553
|
+
*/
|
|
2554
|
+
type Where<T extends Record<string, any> | readonly string[], U> = T extends readonly string[] ? Include<T[number], U> : {
|
|
2555
|
+
[K in keyof T]: K extends U ? K : never;
|
|
2556
|
+
}[keyof T];
|
|
2557
|
+
/**
|
|
2558
|
+
* Allows filtering down `T` to those which extend a given type `U`.
|
|
2559
|
+
*
|
|
2560
|
+
* - `T` is either a dictionary (where keys will be used to compare) or
|
|
2561
|
+
* a readonly sting array.
|
|
2562
|
+
* ```ts
|
|
2563
|
+
* const arr = ["foo", "bar", "baz"];
|
|
2564
|
+
* // "foo"
|
|
2565
|
+
* type F = WhereNot<typeof arr, `ba${string}`>;
|
|
2566
|
+
* ```
|
|
2567
|
+
*/
|
|
2568
|
+
type WhereNot<T extends Record<string, any> | readonly string[], U> = T extends readonly string[] ? Exclude<T[number], U> : {
|
|
2569
|
+
[K in keyof T]: K extends U ? never : K;
|
|
2570
|
+
}[keyof T];
|
|
2571
|
+
|
|
2572
|
+
type AppendToObject<T, U extends keyof any, V> = {
|
|
2573
|
+
[K in keyof T | U]: K extends keyof T ? T[K] : V;
|
|
2574
|
+
};
|
|
2575
|
+
/**
|
|
2576
|
+
* Appends a new Key/Value to an existing dictionary <T>
|
|
2577
|
+
*/
|
|
2578
|
+
type AppendToDictionary<TDict, TKey extends string, TValue> = {
|
|
2579
|
+
[K in keyof TDict | TKey]: K extends keyof TDict ? TDict[K] : TValue;
|
|
2580
|
+
};
|
|
2581
|
+
|
|
2582
|
+
/**
|
|
2583
|
+
* Accepts the `true` literal or _undefined_.
|
|
2584
|
+
*/
|
|
2585
|
+
type MaybeTrue = true | undefined;
|
|
2586
|
+
/**
|
|
2587
|
+
* Accepts the `false` literal or _undefined_.
|
|
2588
|
+
*/
|
|
2589
|
+
type MaybeFalse = false | undefined;
|
|
2590
|
+
|
|
2591
|
+
/**
|
|
2592
|
+
* A conditional clause used in the application of the `ifTypeOf` utility
|
|
2593
|
+
*/
|
|
2594
|
+
type ExtendsClause<N extends Narrowable, TValue extends Record<keyof TValue, N> | number | string | boolean | symbol> = <TBase extends any>(base: TBase) => TValue extends TBase ? true : false;
|
|
2595
|
+
/**
|
|
2596
|
+
* A conditional clause used in the application of the `ifTypeOf` utility
|
|
2597
|
+
*/
|
|
2598
|
+
type ExtendsNarrowlyClause<N extends Narrowable, TValue extends Record<keyof TValue, N> | number | string | boolean | symbol> = <NB extends Narrowable, TBase extends Record<keyof TBase, NB> | number | string | boolean | symbol>(base: TBase) => TValue extends TBase ? true : false;
|
|
2599
|
+
/**
|
|
2600
|
+
* **TypeCondition**
|
|
2601
|
+
*
|
|
2602
|
+
* A partially applied type from the `ifTypeOf` utility where the base type has been
|
|
2603
|
+
* defined and we now need to express the type which is intended to extend it.
|
|
2604
|
+
*
|
|
2605
|
+
* - `extends` - compares with _wide_ types
|
|
2606
|
+
* - `narrowlyExtends` - compares with _narrow_ / _literal_ types
|
|
2607
|
+
*/
|
|
2608
|
+
type TypeCondition<N extends Narrowable, TValue extends Record<keyof TValue, N> | number | string | boolean | symbol> = {
|
|
2609
|
+
extends: ExtendsClause<N, TValue>;
|
|
2610
|
+
narrowlyExtends: ExtendsNarrowlyClause<N, TValue>;
|
|
2611
|
+
};
|
|
2612
|
+
|
|
2613
|
+
/**
|
|
2614
|
+
* **RuleDefinition**
|
|
2615
|
+
*
|
|
2616
|
+
* A rule definition is the typing for the fluent API surface that is built up
|
|
2617
|
+
* with the **ruleset** utility.
|
|
2618
|
+
*/
|
|
2619
|
+
type RuleDefinition<
|
|
2620
|
+
/** the data which will be evaluated on rule execution */
|
|
2621
|
+
T extends object,
|
|
2622
|
+
/** the optional props -- as a union type -- which must be defined per the rule */
|
|
2623
|
+
H extends string = "",
|
|
2624
|
+
/** the key/values which will be evaluated on execution (wide type) */
|
|
2625
|
+
E extends Partial<SameKeys<T>> = {},
|
|
2626
|
+
/** the key/values which will be evaluated on execution (narrow type) */
|
|
2627
|
+
N extends Partial<SameKeys<T>> = {}> = {
|
|
2628
|
+
/**
|
|
2629
|
+
* sets up a true/false check that a given property is defined; this
|
|
2630
|
+
* condition can only be applied to _optional_ properties.
|
|
2631
|
+
*/
|
|
2632
|
+
has(optProp: OptionalKeys<T>): RuleDefinition<T, H & typeof optProp, E, N>;
|
|
2633
|
+
/**
|
|
2634
|
+
* Validates that a given property extends a certain value's type; comparison
|
|
2635
|
+
* is made assuming "wide types".
|
|
2636
|
+
*/
|
|
2637
|
+
equals<K extends keyof T, V extends Pick<T, K>>(prop: K, value: V): RuleDefinition<T, H, E & Record<K, V>, N>;
|
|
2638
|
+
/**
|
|
2639
|
+
* Validates that a given property extends a certain value's type; comparison
|
|
2640
|
+
* is made assuming "narrow types". This is only available for props which
|
|
2641
|
+
* expose a
|
|
2642
|
+
*/
|
|
2643
|
+
narrowlyEquals<K extends keyof T, V extends Pick<T, K>>(prop: K, value: V): RuleDefinition<T, H, E, N & Record<K, V>>;
|
|
2644
|
+
};
|
|
2645
|
+
/**
|
|
2646
|
+
* **DynamicRule**
|
|
2647
|
+
*
|
|
2648
|
+
* A dynamic rule allows type and runtime validation of a data structure
|
|
2649
|
+
* which extends a known `State`. It then returns the literal type `true`
|
|
2650
|
+
* or `false`.
|
|
2651
|
+
*
|
|
2652
|
+
* ```ts
|
|
2653
|
+
* type State = { id?: string; favorite: boolean; color: string };
|
|
2654
|
+
* // type-safe way to check whether optional prop is actually set
|
|
2655
|
+
* const rule: DynamicRule<State> = s => s
|
|
2656
|
+
* .has("id")
|
|
2657
|
+
* .equals("favorite", true)
|
|
2658
|
+
* .equals("color", "red");
|
|
2659
|
+
* ```
|
|
2660
|
+
*/
|
|
2661
|
+
type DynamicRule<TState extends any, TResult extends true | false> = (rule: TypeCondition<any, TState>) => TResult;
|
|
2662
|
+
/**
|
|
2663
|
+
* **DynamicRuleSet**
|
|
2664
|
+
*
|
|
2665
|
+
* A function which accepts the agreed `TState` generic as input and returns a discrete
|
|
2666
|
+
* `true` or `false` value.
|
|
2667
|
+
*/
|
|
2668
|
+
type DynamicRuleSet<TState extends any, TRules extends Record<string, TypeCondition<any, TState>>> = (rules: TRules) => true | false;
|
|
2669
|
+
|
|
2670
|
+
type RuntimeType<T> = {
|
|
2671
|
+
__kind: "type";
|
|
2672
|
+
type: T;
|
|
2673
|
+
is: TypeGuard<T>;
|
|
2674
|
+
};
|
|
2675
|
+
type RuntimeProp<P extends Readonly<PropertyKey>, T extends RuntimeType<any>> = {
|
|
2676
|
+
__kind: "prop";
|
|
2677
|
+
key: Readonly<P>;
|
|
2678
|
+
valueType: Readonly<T["type"]>;
|
|
2679
|
+
/**
|
|
2680
|
+
* Provides the _type_ to the type system when used with `typeof`.
|
|
2681
|
+
*
|
|
2682
|
+
* ```ts
|
|
2683
|
+
* const t = number();
|
|
2684
|
+
* // number
|
|
2685
|
+
* type T = typeof t.type;
|
|
2686
|
+
* ```
|
|
2687
|
+
*
|
|
2688
|
+
* **Note:** _the runtime system will get a string equivalent name:_
|
|
2689
|
+
* ```ts
|
|
2690
|
+
* const t = number();
|
|
2691
|
+
* // "number"
|
|
2692
|
+
* console.log(t.type);
|
|
2693
|
+
* ```
|
|
2694
|
+
*/
|
|
2695
|
+
type: Record<P, T["type"]>;
|
|
2696
|
+
is: TypeGuard<Record<P, T["type"]>>;
|
|
2697
|
+
};
|
|
2698
|
+
type TypeOptions<T extends Partial<object> = {}> = {
|
|
2699
|
+
/** each type has a default type guard but you can override if you need to be more specific */
|
|
2700
|
+
typeGuard?: TypeGuard<T>;
|
|
2701
|
+
} & T;
|
|
2702
|
+
|
|
2703
|
+
/**
|
|
2704
|
+
* Validates that a given type extends another and returns `true` or `false` type
|
|
2705
|
+
*/
|
|
2706
|
+
type ExpectExtends<VALUE, EXPECTED> = EXPECTED extends VALUE ? true : false;
|
|
2707
|
+
/**
|
|
2708
|
+
* Validates that a given type extends another and returns `any` or `never` as a type
|
|
2709
|
+
*/
|
|
2710
|
+
type AssertExtends<VALUE, EXPECTED> = EXPECTED extends VALUE ? any : never;
|
|
2711
|
+
/**
|
|
2712
|
+
* Give a type `TValue` and a comparison type `TExtends`
|
|
2713
|
+
*/
|
|
2714
|
+
type IfExtendsThen<VALUE, EXPECTED, THEN> = EXPECTED extends VALUE ? THEN : never;
|
|
2715
|
+
|
|
2716
|
+
/**
|
|
2717
|
+
* **ToFluent**
|
|
2718
|
+
*
|
|
2719
|
+
* Converts the typing of a dictionary of functions into the same
|
|
2720
|
+
* function signatures but changes the return type to be the Fluent API.
|
|
2721
|
+
*
|
|
2722
|
+
* **Note:** this utility also allows a non-fluent API surface `X` to be included as
|
|
2723
|
+
* part of the API surface if this is desired.
|
|
2724
|
+
*/
|
|
2725
|
+
type ToFluent<T extends {
|
|
2726
|
+
[key: string]: (...args: any[]) => any;
|
|
2727
|
+
}, X extends object = {}> = {
|
|
2728
|
+
[K in keyof T]: (...args: Parameters<T[K]>) => ToFluent<T, X> & X;
|
|
2729
|
+
} & X;
|
|
2730
|
+
/**
|
|
2731
|
+
* A _pure_ Fluent API which promotes an API surface where _every_ API endpoint must be a function
|
|
2732
|
+
* which returns the same API surface.
|
|
2733
|
+
*
|
|
2734
|
+
* To provide value, this style of Fluent API will need to perform useful _side effects_ when functions
|
|
2735
|
+
* on the API surface are called as this structure does not provide any means to maintain an internal state
|
|
2736
|
+
* which can be returned later.
|
|
2737
|
+
*
|
|
2738
|
+
* **Note:** _if you prefer a Fluent API with means to _escape_ with an internally managed state then
|
|
2739
|
+
* you should prefer the use of the `FluentApi` type._
|
|
2740
|
+
*/
|
|
2741
|
+
type PureFluentApi<TApi extends Record<string, (...args: any[]) => PureFluentApi<TApi, any>>, TExclude extends string = ""> = {
|
|
2742
|
+
[P in keyof TApi]: (...args: Parameters<TApi[P]>) => PureFluentApi<Omit<TApi, TExclude>>;
|
|
2743
|
+
};
|
|
2744
|
+
|
|
2745
|
+
export { AfterFirst, AllCaps, Alpha, AlphaNumeric, AnyFunction, Api, ApiFunction, ApiValue, AppendToDictionary, AppendToObject, ArrConcat, Array$1 as Array, ArrayConverter, AsArray, AsFinalizedConfig, AssertExtends, Box, BoxValue, BoxedFnParams, BoxedReturn, Bracket, Break, CamelCase, CapitalizeWords, Cardinality, Cardinality0, Cardinality1, CardinalityExplicit, CardinalityFilter0, CardinalityFilter1, CardinalityIn, CardinalityInput, CardinalityNode, CardinalityOut, CardinalityTuple, ClosingBracket, Condition, ConditionFilter, Configurator, ConfiguredMap, Constructor, Contains, DEFAULT_MANY_TO_ONE_MAPPING, DEFAULT_ONE_TO_MANY_MAPPING, DEFAULT_ONE_TO_ONE_MAPPING, DashToSnake, DashUppercase, Dasherize, DecomposeMapConfig, DefaultManyToOneMapping, DefaultOneToManyMapping, DefaultOneToOneMapping, DefinePropertiesApi, DictArrApi, DictArray, DictArrayFilterCallback, DictArrayKv, DictChangeValue, DictFromKv, DictKvTuple, DictPartialApplication, DictPrependWithFn, DictReturnValues, DictionaryWithoutValue, DomainName, DynamicRule, DynamicRuleSet, Email, EndsWith, EnsureLeading, EnsureTrailing, EnumValues, ExpandRecursively, ExpectExtends, ExplicitFunction, Extends, FilterContains, FilterDefn, FilterEnds, FilterEquals, FilterFn, FilterGreaterThan, FilterIs, FilterLessThan, FilterNotEqual, FilterStarts, FilterTuple, FinalReturn, FinalizedMapConfig, First, FirstKey, FirstKeyValue, FirstOfEach, FirstOrUndefined, FirstString, FluentConfigurator, FluentFunction, FnShape, FromDictArray, FullyQualifiedUrl, FunctionType, GeneralDictionary, Get, HasParameters, HasUppercase, HybridFunction, IConfigurator, IFluentConfigurator, If, IfArray, IfBooleanLiteral, IfEndsWith, IfExtends, IfExtendsThen, IfFalse, IfLiteral, IfNumericLiteral, IfObject, IfOptionalLiteral, IfReadonlyArray, IfScalar, IfStartsWith, IfStringLiteral, IfTrue, IfUndefined, Include, Includes, IntersectingKeys, Ipv4, IsArray, IsBoolean, IsBooleanLiteral, IsCapitalized, IsEqual, IsFalse, IsFunction, IsLiteral, IsNull, IsNumber, IsNumericLiteral, IsObject, IsOptionalLiteral, IsReadonlyArray, IsScalar, IsStringLiteral, IsTrue, IsUndefined, KebabCase, KeyValue, KeyedRecord, Keys, KeysWithValue, KvFrom, KvTuple, LastInUnion, LeftWhitespace, Length, LogicFunction, LogicalCombinator, LowerAllCaps, LowerAlpha, ManyToMany, ManyToOne, ManyToZero, MapCard, MapCardinality, MapCardinalityFrom, MapCardinalityIllustrated, MapConfig, MapFn, MapFnInput, MapFnOutput, MapIR, MapInput, MapInputFrom, MapOR, MapOutput, MapOutputFrom, MapTo, Mapper, MapperApi, MaybeFalse, MaybeTrue, Mutable, MutableProps, NarrowBox, Narrowable, NarrowlyContains, NetworkProtocol, NonAlpha, NonNumericKeys, NonStringKeys, Not, NotEqual, NotFilter, Numeric, NumericFilter, NumericKeys, NumericString, ObjectType, OneToMany, OneToOne, OneToZero, Opaque, OpeningBracket, OptRequired, OptionalKeys, OptionalProps, Or, Parenthesis, PascalCase, PathJoin, Pluralize, PrivateKey, PrivateKeys, PublicKeys, Punctuation, PureFluentApi, RelativeUrl, Replace, RequireProps, RequiredKeys, RequiredProps, Retain, RightWhitespace, RuleDefinition, RuntimeProp, RuntimeType, SameKeys, SecondOfEach, SimpleFunction, SimplifyObject, SnakeCase, SpecialCharacters, Split, StartsWith, StringDelimiter, StringFilter, StringKeys, StringLength, StripLeading, StripTrailing, Suggest, SuggestNumeric, ToFluent, Transformer, Trim, TrimLeft, TrimRight, TupleToUnion, Type, TypeApi, TypeDefault, TypeDefinition, TypeGuard, TypeOptions, Unbox, UndefinedArrayIsUnknown, UndefinedTreatment, UndefinedValue, UnionToIntersection, UnionToTuple, UniqueDictionary, UniqueForProp, Uniqueness, UnwrapNot, UpperAlpha, UrlBuilder, VariableName, Where, WhereNot, Whitespace, Widen, WithNumericKeys, WithStringKeys, WithValue, ZeroToMany, ZeroToOne, ZeroToZero, ZipCode, and, api, arrayToKeyLookup, arrayToObject, asArray, box, boxDictionaryValues, condition, createConverter, createFnWithProps, defineProperties, defineType, dictArr, dictToKv, dictionaryTransform, ensureLeading, ensureTrailing, entries, filter, filterDictArray, fnWithProps, groupBy, idLiteral, idTypeGuard, identity, ifArray, ifArrayPartial, ifBoolean, ifDefined, ifFalse, ifNull, ifNumber, ifObject, ifSameType, ifString, ifTrue, ifUndefined, isArray, isBoolean, isBox, isFalse, isFunction, isNotFilter, isNull, isNumber, isNumericFilter, isObject, isString, isSymbol, isTrue, isType, isUndefined, keys, kindLiteral, kv, kvToDict, literal, mapTo, mapToDict, mapToFn, mapValues, nameLiteral, not, or, pathJoin, readonlyFnWithProps, ruleSet, strArrayToDict, stripTrailing, type, typeApi, unbox, wide, withValue };
|