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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inferred-types",
3
- "version": "0.22.7",
3
+ "version": "0.22.8",
4
4
  "description": "Functions which provide useful type inference on TS projects",
5
5
  "license": "MIT",
6
6
  "author": "Ken Snyder<ken@ken.net>",
@@ -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
+ });