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
|
@@ -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
|
+
});
|