inferred-types 0.22.7 → 0.22.8
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
CHANGED
|
@@ -584,6 +584,25 @@ O extends (...args: any[]) => any = (...args: any[]) => any> = SimplifyObject<{
|
|
|
584
584
|
*/
|
|
585
585
|
declare 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;
|
|
586
586
|
|
|
587
|
+
/**
|
|
588
|
+
* Maps from one type `I` to another `O`, where:
|
|
589
|
+
*
|
|
590
|
+
* - a **null** value indicates that there is no valid mapping for the given input
|
|
591
|
+
* - you can either return a 1:1 or 1:M output as `O` or `O[]` when there is a mapping
|
|
592
|
+
*
|
|
593
|
+
* This type utility will ensure both `I` and `O` are honoured but if the runtime only
|
|
594
|
+
* uses the type utility it's worth bearing in mind that while _typing_ will be as expected
|
|
595
|
+
* the output parameter can assume properties that in fact do not reside
|
|
596
|
+
*
|
|
597
|
+
* ```ts
|
|
598
|
+
* const mapper: ModelMapper<{title: string}, {title: string, kind: string}> = i => {
|
|
599
|
+
* title: i.title,
|
|
600
|
+
* kind: "markdown"
|
|
601
|
+
* }
|
|
602
|
+
* ```
|
|
603
|
+
*/
|
|
604
|
+
declare type MapTo<I extends {}, O extends {}> = (i: I) => O[];
|
|
605
|
+
|
|
587
606
|
/**
|
|
588
607
|
* Given a dictionary of type `<T>`, this utility function will
|
|
589
608
|
* make the `<M>` generic property _mutable_ and all other _read-only_.
|
|
@@ -1702,4 +1721,4 @@ interface IFluentConfigurator<C> {
|
|
|
1702
1721
|
*/
|
|
1703
1722
|
declare function FluentConfigurator<I>(initial?: I): IFluentConfigurator<{}>;
|
|
1704
1723
|
|
|
1705
|
-
export { AllCaps, Alpha, AlphaNumeric, Api, ApiFunction, ApiValue, AppendToDictionary, AppendToObject, ArrConcat, Array$1 as Array, ArrayConverter, AssertExtends, Bracket, Break, CamelCase, CapitalizeWords, ClosingBracket, Condition, Configurator, Constructor, DashToSnake, DashUppercase, Dasherize, DefinePropertiesApi, DictArray, DictArrayFilterCallback, DictArrayKv, DictChangeValue, DictFromKv, DictKvTuple, DictPartialApplication, DictPrependWithFn, DictReturnValues, DynamicRule, DynamicRuleSet, Email, EnumValues, ExpandRecursively, ExpectExtends, ExplicitFunction, ExtendsClause, ExtendsNarrowlyClause, Filter, FinalReturn, First, FirstKey, FirstKeyValue, FirstOfEach, FluentConfigurator, FluentFunction, FromDictArray, FunctionType, GeneralDictionary, Get, HasUppercase, IConfigurator, IFluentConfigurator, If, IfExtends, IfExtendsThen, Include, Includes, IsArray, IsBoolean, IsCapitalized, IsFalse, IsFunction, IsObject, IsString, IsTrue, KebabCase, KeyValue, KeyedRecord, Keys, KeysWithValue, KvFrom, KvTuple, LastInUnion, LeftWhitespace, Length, LowerAllCaps, LowerAlpha, MaybeFalse, MaybeTrue, Model, Mutable, MutableProps, MutationFunction, MutationIdentity, Narrowable, NonAlpha, NonNumericKeys, NonStringKeys, Not, Numeric, NumericKeys, NumericString, ObjectType, Opaque, OpeningBracket, OptionalKeys, OptionalProps, Parenthesis, PascalCase, Pluralize, PrivateKey, PrivateKeys, PublicKeys, Punctuation, PureFluentApi, Replace, RequireProps, RequiredKeys, RequiredProps, Retain, RightWhitespace, RuleDefinition, RuntimeProp, RuntimeType, SameKeys, SecondOfEach, SimplifyObject, SnakeCase, SpecialCharacters, StringDelimiter, StringKeys, StringLength, ToFluent, Transformer, Trim, TrimLeft, TrimRight, TupleToUnion, Type, TypeApi, TypeCondition, TypeDefinition, TypeGuard, TypeOptions, UnionToIntersection, UnionToTuple, UniqueDictionary, UniqueForProp, UpperAlpha, ValueTuple, ValueTypeFunc, ValueTypes, Where, WhereNot, Whitespace, WithNumericKeys, WithStringKeys, WithValue, ZipCode, and, api, arrayToKeyLookup, arrayToObject, condition, createFnWithProps, createMutationFunction, defineProperties, defineType, dictToKv, dictionaryTransform, entries, equals, filterDictArray, fnWithProps, greater, groupBy, idLiteral, idTypeGuard, identity, ifTypeOf, isArray, isBoolean, isFalse, isFunction, isNull, isNumber, isObject, isString, isSymbol, isTrue, isType, isUndefined, keys, kindLiteral, kv, kvToDict, less, literal, mapValues, nameLiteral, or, randomString, readonlyFnWithProps, ruleSet, strArrayToDict, type, typeApi, uuid, valueTypes, withValue };
|
|
1724
|
+
export { AllCaps, Alpha, AlphaNumeric, Api, ApiFunction, ApiValue, AppendToDictionary, AppendToObject, ArrConcat, Array$1 as Array, ArrayConverter, AssertExtends, Bracket, Break, CamelCase, CapitalizeWords, ClosingBracket, Condition, Configurator, Constructor, DashToSnake, DashUppercase, Dasherize, DefinePropertiesApi, DictArray, DictArrayFilterCallback, DictArrayKv, DictChangeValue, DictFromKv, DictKvTuple, DictPartialApplication, DictPrependWithFn, DictReturnValues, DynamicRule, DynamicRuleSet, Email, EnumValues, ExpandRecursively, ExpectExtends, ExplicitFunction, ExtendsClause, ExtendsNarrowlyClause, Filter, FinalReturn, First, FirstKey, FirstKeyValue, FirstOfEach, FluentConfigurator, FluentFunction, FromDictArray, FunctionType, GeneralDictionary, Get, HasUppercase, IConfigurator, IFluentConfigurator, If, IfExtends, IfExtendsThen, Include, Includes, IsArray, IsBoolean, IsCapitalized, IsFalse, IsFunction, IsObject, IsString, IsTrue, KebabCase, KeyValue, KeyedRecord, Keys, KeysWithValue, KvFrom, KvTuple, LastInUnion, LeftWhitespace, Length, LowerAllCaps, LowerAlpha, MapTo, MaybeFalse, MaybeTrue, Model, Mutable, MutableProps, MutationFunction, MutationIdentity, Narrowable, NonAlpha, NonNumericKeys, NonStringKeys, Not, Numeric, NumericKeys, NumericString, ObjectType, Opaque, OpeningBracket, OptionalKeys, OptionalProps, Parenthesis, PascalCase, Pluralize, PrivateKey, PrivateKeys, PublicKeys, Punctuation, PureFluentApi, Replace, RequireProps, RequiredKeys, RequiredProps, Retain, RightWhitespace, RuleDefinition, RuntimeProp, RuntimeType, SameKeys, SecondOfEach, SimplifyObject, SnakeCase, SpecialCharacters, StringDelimiter, StringKeys, StringLength, ToFluent, Transformer, Trim, TrimLeft, TrimRight, TupleToUnion, Type, TypeApi, TypeCondition, TypeDefinition, TypeGuard, TypeOptions, UnionToIntersection, UnionToTuple, UniqueDictionary, UniqueForProp, UpperAlpha, ValueTuple, ValueTypeFunc, ValueTypes, Where, WhereNot, Whitespace, WithNumericKeys, WithStringKeys, WithValue, ZipCode, and, api, arrayToKeyLookup, arrayToObject, condition, createFnWithProps, createMutationFunction, defineProperties, defineType, dictToKv, dictionaryTransform, entries, equals, filterDictArray, fnWithProps, greater, groupBy, idLiteral, idTypeGuard, identity, ifTypeOf, isArray, isBoolean, isFalse, isFunction, isNull, isNumber, isObject, isString, isSymbol, isTrue, isType, isUndefined, keys, kindLiteral, kv, kvToDict, less, literal, mapValues, nameLiteral, or, randomString, readonlyFnWithProps, ruleSet, strArrayToDict, type, typeApi, uuid, valueTypes, withValue };
|
package/package.json
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps from one type `I` to another `O`, where:
|
|
3
|
+
*
|
|
4
|
+
* - a **null** value indicates that there is no valid mapping for the given input
|
|
5
|
+
* - you can either return a 1:1 or 1:M output as `O` or `O[]` when there is a mapping
|
|
6
|
+
*
|
|
7
|
+
* This type utility will ensure both `I` and `O` are honoured but if the runtime only
|
|
8
|
+
* uses the type utility it's worth bearing in mind that while _typing_ will be as expected
|
|
9
|
+
* the output parameter can assume properties that in fact do not reside
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* const mapper: ModelMapper<{title: string}, {title: string, kind: string}> = i => {
|
|
13
|
+
* title: i.title,
|
|
14
|
+
* kind: "markdown"
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export type MapTo<I extends {}, O extends {}> = (i: I) => O[];
|
|
@@ -9,6 +9,7 @@ export * from "./DictChangeValue";
|
|
|
9
9
|
export * from "./DictPrependWithFn";
|
|
10
10
|
export * from "./DictReturnValues";
|
|
11
11
|
export * from "./Get";
|
|
12
|
+
export * from "./MapTo";
|
|
12
13
|
export * from "./MutableProps";
|
|
13
14
|
export * from "./RequireProps";
|
|
14
15
|
export * from "./SameKeys";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MapTo } from "src/types/dictionary";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* **mapTo**
|
|
5
|
+
*
|
|
6
|
+
* A utility function which maps one dictionary structure `I` to another `O`; where:
|
|
7
|
+
*
|
|
8
|
+
* - `I` maps to `O[ ]` so this allows a cardinality of 0:M
|
|
9
|
+
* - In other words ... values from `I` can be filtered, translated 1:1 or split into multiple outputs
|
|
10
|
+
* - Type constrains laid out by `I` and `O` will be enforced by type system
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* type I = { title: string; color: string; products: Product[] };
|
|
14
|
+
* type O = { title: string; count: number };
|
|
15
|
+
* const summarize: mapTo<I,O>()
|
|
16
|
+
* .map();
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export const mapTo =
|
|
20
|
+
<I extends {}, O extends {}>(cb: MapTo<I, O>) =>
|
|
21
|
+
(source: I) =>
|
|
22
|
+
cb(source);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { MapTo } from "src/types/dictionary";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
import type { Expect, Equal } from "@type-challenges/utils";
|
|
5
|
+
import { mapTo } from "src/utility/dictionary/mapTo";
|
|
6
|
+
|
|
7
|
+
type I = { title: string; color: string; products: string[] };
|
|
8
|
+
const i: I = { title: "Test", color: "green", products: ["foo", "bar", "baz"] };
|
|
9
|
+
|
|
10
|
+
type O = { title: string; count: number; unnecessary?: number };
|
|
11
|
+
|
|
12
|
+
describe("MapTo<T> type util", () => {
|
|
13
|
+
it("1:1 conversion", () => {
|
|
14
|
+
const m: MapTo<I, O> = (i) => [
|
|
15
|
+
{
|
|
16
|
+
title: i.title,
|
|
17
|
+
count: i.products.length,
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
type M = typeof m;
|
|
21
|
+
type cases = [Expect<Equal<M, MapTo<I, O>>>];
|
|
22
|
+
const cases: cases = [true];
|
|
23
|
+
expect(cases).toBe(cases);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("1:1 conversion with non-required", () => {
|
|
27
|
+
const m: MapTo<I, O> = (i) => [
|
|
28
|
+
{
|
|
29
|
+
title: i.title,
|
|
30
|
+
count: i.products.length,
|
|
31
|
+
unnecessary: 42,
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
type M = typeof m;
|
|
35
|
+
type cases = [Expect<Equal<M, MapTo<I, O>>>];
|
|
36
|
+
const cases: cases = [true];
|
|
37
|
+
expect(cases).toBe(cases);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("1:M conversion", () => {
|
|
41
|
+
const m: MapTo<I, O> = (i) => [
|
|
42
|
+
{
|
|
43
|
+
title: i.title,
|
|
44
|
+
count: i.products.length,
|
|
45
|
+
unnecessary: 1,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
title: i.title,
|
|
49
|
+
count: i.products.length + 1,
|
|
50
|
+
unnecessary: 2,
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
type M = typeof m;
|
|
54
|
+
type cases = [Expect<Equal<M, MapTo<I, O>>>];
|
|
55
|
+
const cases: cases = [true];
|
|
56
|
+
expect(cases).toBe(cases);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("filter input as 1:0 cardinality", () => {
|
|
60
|
+
const m: MapTo<I, O> = (_i) => [];
|
|
61
|
+
type M = typeof m;
|
|
62
|
+
type cases = [Expect<Equal<M, MapTo<I, O>>>];
|
|
63
|
+
const cases: cases = [true];
|
|
64
|
+
expect(cases).toBe(cases);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe("mapTo() utility function", () => {
|
|
69
|
+
it("test 1:1 mapping", () => {
|
|
70
|
+
const m = mapTo<I, O>((i) => [
|
|
71
|
+
{
|
|
72
|
+
title: i.title,
|
|
73
|
+
count: i.products.length,
|
|
74
|
+
},
|
|
75
|
+
]);
|
|
76
|
+
type M = typeof m;
|
|
77
|
+
type R = ReturnType<M>;
|
|
78
|
+
|
|
79
|
+
// runtime
|
|
80
|
+
expect(m(i)).toEqual([{ title: i.title, count: i.products.length }]);
|
|
81
|
+
// types
|
|
82
|
+
type cases = [Expect<Equal<R, O[]>>];
|
|
83
|
+
const cases: cases = [true];
|
|
84
|
+
expect(cases).toBe(cases);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("test 1:1 mapping with extraneous prop", () => {
|
|
88
|
+
const m = mapTo<I, O>((i) => [
|
|
89
|
+
{
|
|
90
|
+
title: i.title,
|
|
91
|
+
count: i.products.length,
|
|
92
|
+
extraneous: 42,
|
|
93
|
+
},
|
|
94
|
+
]);
|
|
95
|
+
type M = typeof m;
|
|
96
|
+
type R = ReturnType<M>;
|
|
97
|
+
|
|
98
|
+
// runtime
|
|
99
|
+
// TODO: extraneous props are cut out of the type but still allows us to return `O` values with extraneous props!
|
|
100
|
+
// expect(m(i)).toEqual([{ title: i.title, count: i.products.length }]);
|
|
101
|
+
// types
|
|
102
|
+
type cases = [Expect<Equal<R, O[]>>];
|
|
103
|
+
const cases: cases = [true];
|
|
104
|
+
expect(cases).toBe(cases);
|
|
105
|
+
});
|
|
106
|
+
});
|