inferred-types 0.22.6 → 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
@@ -522,6 +522,14 @@ declare type DictPartialApplication<T extends Record<string, any>, I extends boo
522
522
  * the original object `I` so long as the original value for the KV pair extends `V`.
523
523
  *
524
524
  * If `V` is not specified then it defaults to _any_ and therefore all KVs are preserved.
525
+ *
526
+ * ```ts
527
+ * type Obj = { foo: "hello", bar: 42, baz: () => "world" };
528
+ * // { foo: number, bar: number, baz: number };
529
+ * type AllNumbers = DictChangeValue<Obj, number>;
530
+ * // { foo: number }
531
+ * type StringToBool = DictChangeValue<Obj, boolean, string>
532
+ * ```
525
533
  */
526
534
  declare type DictChangeValue<
527
535
  /** the object who's value-type we're changing */
@@ -576,6 +584,25 @@ O extends (...args: any[]) => any = (...args: any[]) => any> = SimplifyObject<{
576
584
  */
577
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;
578
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
+
579
606
  /**
580
607
  * Given a dictionary of type `<T>`, this utility function will
581
608
  * make the `<M>` generic property _mutable_ and all other _read-only_.
@@ -1694,4 +1721,4 @@ interface IFluentConfigurator<C> {
1694
1721
  */
1695
1722
  declare function FluentConfigurator<I>(initial?: I): IFluentConfigurator<{}>;
1696
1723
 
1697
- 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.6",
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>",
@@ -5,6 +5,14 @@ import { SimplifyObject } from "../SimplifyObject";
5
5
  * the original object `I` so long as the original value for the KV pair extends `V`.
6
6
  *
7
7
  * If `V` is not specified then it defaults to _any_ and therefore all KVs are preserved.
8
+ *
9
+ * ```ts
10
+ * type Obj = { foo: "hello", bar: 42, baz: () => "world" };
11
+ * // { foo: number, bar: number, baz: number };
12
+ * type AllNumbers = DictChangeValue<Obj, number>;
13
+ * // { foo: number }
14
+ * type StringToBool = DictChangeValue<Obj, boolean, string>
15
+ * ```
8
16
  */
9
17
  export type DictChangeValue<
10
18
  /** the object who's value-type we're changing */
@@ -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
+ });