inferred-types 0.27.0 → 0.28.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.
@@ -1,10 +1,17 @@
1
+ /* eslint-disable no-use-before-define */
1
2
  import { OptRequired } from "src/types/literal-unions";
3
+ import {
4
+ DefaultManyToOneMapping,
5
+ DefaultOneToManyMapping,
6
+ DefaultOneToOneMapping,
7
+ } from "src/utility/dictionary/mapTo";
2
8
  import { EnumValues } from "../EnumValues";
9
+ import { TypeDefault } from "../TypeInfo/TypeDefault";
3
10
 
4
11
  /**
5
12
  * Expresses relationship between inputs/outputs:
6
13
  */
7
- export enum MapDirection {
14
+ export enum MapCardinality {
8
15
  /** every input results in 0:M outputs */
9
16
  OneToMany = "I -> O[]",
10
17
  /** every input results in 0:1 outputs */
@@ -13,35 +20,230 @@ export enum MapDirection {
13
20
  ManyToOne = "I[] -> O",
14
21
  }
15
22
 
16
- export type MapDirectionVal = EnumValues<MapDirection>;
23
+ export type MapCardinalityIllustrated = EnumValues<MapCardinality>;
17
24
 
18
- export type MapInput<I, IR, D extends MapDirectionVal> = D extends
19
- | MapDirection.OneToMany
20
- | "I -> O[]"
25
+ /**
26
+ * The _user_ configuration of a **mapTo** mapper function
27
+ * which will be finalized by merging it with the appropriate
28
+ * default mapping type.
29
+ */
30
+ export interface MapConfig<
31
+ IR extends OptRequired | undefined = undefined,
32
+ D extends MapCardinalityIllustrated | undefined = undefined,
33
+ OR extends OptRequired | undefined = undefined
34
+ > {
35
+ input?: IR;
36
+ output?: OR;
37
+ cardinality?: D;
38
+ }
39
+
40
+ /**
41
+ * A finalized configuration of a **mapTo** mapper functions cardinality
42
+ * relationships between _inputs_ and _outputs_.
43
+ *
44
+ * Note: _this configuration does _not_ yet include the actual mapping
45
+ * configuration between the input and output._
46
+ */
47
+ export type FinalizedMapConfig<
48
+ IR extends OptRequired,
49
+ D extends MapCardinalityIllustrated,
50
+ OR extends OptRequired
51
+ > = Required<MapConfig<IR, D, OR>> & { finalized: true };
52
+
53
+ /**
54
+ * User configuration exposed by a config function which specifies the
55
+ * cardinality already (e.g., `oneToMany()`, `manyToOne()`)
56
+ */
57
+ type MapCardinalityConfig<
58
+ IR extends OptRequired | undefined,
59
+ OR extends OptRequired | undefined
60
+ > = {
61
+ input?: IR;
62
+ output?: OR;
63
+ };
64
+
65
+ /**
66
+ * **ConfiguredMap**
67
+ *
68
+ * A partial application of the mapTo() utility which has expressed the
69
+ * configuration of the _inputs_ and _outputs_ and provides a `.map()`
70
+ * method which allows the user configure the specifics of the mapping.
71
+ */
72
+ export type ConfiguredMap<
73
+ C extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>
74
+ > = {
75
+ map: <I, O>(map: MapTo<I, O, C>) => MapFn<I, O, C>;
76
+ input: MapIR<C>;
77
+ cardinality: MapCard<C>;
78
+ output: MapOR<C>;
79
+ };
80
+
81
+ /**
82
+ * Extracts the IR, Cardinality, and OR generics from a FinalizedMapConfig
83
+ */
84
+ export type DecomposeMapConfig<
85
+ M extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>
86
+ > = M extends MapConfig<infer IR, infer D, infer OR>
87
+ ? IR extends OptRequired | undefined
88
+ ? D extends MapCardinalityIllustrated | undefined
89
+ ? OR extends OptRequired | undefined
90
+ ? [IR, D, OR]
91
+ : never
92
+ : never
93
+ : never
94
+ : M extends FinalizedMapConfig<infer IR, infer D, infer OR>
95
+ ? IR extends OptRequired
96
+ ? D extends MapCardinalityIllustrated
97
+ ? OR extends OptRequired
98
+ ? [IR, D, OR]
99
+ : never
100
+ : never
101
+ : never
102
+ : never;
103
+
104
+ /** extracts IR from a `FinalizedMapConfig` */
105
+ export type MapIR<
106
+ T extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>
107
+ > = DecomposeMapConfig<T>[0];
108
+
109
+ /**
110
+ * extracts the MapCardinality from a `FinalizedMapConfig`
111
+ */
112
+ export type MapCard<
113
+ T extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>
114
+ > = DecomposeMapConfig<T>[1];
115
+
116
+ /** extracts OR from a `FinalizedMapConfig` */
117
+ export type MapOR<
118
+ T extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>
119
+ > = DecomposeMapConfig<T>[2];
120
+
121
+ /**
122
+ * Merges the types of a userland configuration with a default configuration
123
+ */
124
+ export type AsFinalizedConfig<
125
+ U extends MapConfig<
126
+ OptRequired | undefined,
127
+ MapCardinalityIllustrated | undefined,
128
+ OptRequired | undefined
129
+ >,
130
+ D extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>
131
+ > = TypeDefault<U, D> extends FinalizedMapConfig<infer IR, infer C, infer OR>
132
+ ? FinalizedMapConfig<IR, C, OR>
133
+ : never;
134
+
135
+ export type MapperApi = {
136
+ /**
137
+ * Provides opportunity to configure _input_, _output_, and _cardinality_
138
+ * prior to providing a mapping function.
139
+ *
140
+ * Note: _the defaults for configuration are defined by the_ `DEFAULT_ONE_TO_MANY_MAPPING`
141
+ * _constant made available as a symbol from this library._
142
+ */
143
+ config: <
144
+ C extends MapConfig<
145
+ OptRequired, //
146
+ MapCardinalityIllustrated,
147
+ OptRequired
148
+ >
149
+ >(
150
+ config: C
151
+ ) => ConfiguredMap<
152
+ AsFinalizedConfig<
153
+ C, //
154
+ DefaultOneToManyMapping
155
+ >
156
+ >;
157
+
158
+ /**
159
+ * Provides a nice 1:1 ratio between the input and output.
160
+ *
161
+ * By default the input and output are considered to be _required_
162
+ * properties but this can be changed with the options hash provided.
163
+ * ```ts
164
+ * const mapper = mapTo.oneToOne().map(...);
165
+ * // add in ability to filter out some inputs
166
+ * const mapAndFilter = mapTo.oneToOne({ output: "opt" })
167
+ * ```
168
+ */
169
+ oneToOne: <C extends MapCardinalityConfig<OptRequired, OptRequired>>(
170
+ config?: C
171
+ ) => ConfiguredMap<
172
+ AsFinalizedConfig<
173
+ C, //
174
+ DefaultOneToOneMapping
175
+ >
176
+ >;
177
+
178
+ /**
179
+ * **manyToOne** _mapping_
180
+ *
181
+ * Provides a configuration where multiple inputs `I[]` will be mapped to a
182
+ * single output `O`.
183
+ *
184
+ * Choosing this configuration will, by default, set both input and output
185
+ * to be "required" but you can change this default if you so choose.
186
+ */
187
+ manyToOne: <
188
+ C extends MapCardinalityConfig<
189
+ OptRequired | undefined, //
190
+ OptRequired | undefined
191
+ >
192
+ >(
193
+ config?: C
194
+ ) => ConfiguredMap<
195
+ AsFinalizedConfig<
196
+ C, //
197
+ DefaultManyToOneMapping
198
+ >
199
+ >;
200
+
201
+ oneToMany: <
202
+ C extends MapCardinalityConfig<
203
+ OptRequired | undefined, //
204
+ OptRequired | undefined
205
+ >
206
+ >(
207
+ config?: C
208
+ ) => ConfiguredMap<
209
+ AsFinalizedConfig<
210
+ C, //
211
+ DefaultOneToManyMapping
212
+ >
213
+ >;
214
+ };
215
+
216
+ export type MapInput<
217
+ I, //
218
+ IR extends OptRequired,
219
+ C extends MapCardinalityIllustrated
220
+ > = C extends MapCardinality.OneToMany | "I -> O[]"
21
221
  ? IR extends "opt"
22
222
  ? I | undefined
23
223
  : I
24
- : D extends MapDirection.OneToOne | "I -> O"
224
+ : C extends MapCardinality.OneToOne | "I -> O"
25
225
  ? IR extends "opt"
26
226
  ? I | undefined
27
227
  : I
28
- : D extends MapDirection.ManyToOne | "I[] -> O"
228
+ : C extends MapCardinality.ManyToOne | "I[] -> O"
29
229
  ? IR extends "opt"
30
230
  ? I[] | undefined
31
231
  : I[]
32
232
  : never;
33
233
 
34
- export type MapOutput<O, OR, D extends MapDirectionVal> = D extends
35
- | MapDirection.OneToMany
36
- | "I -> O[]"
234
+ export type MapOutput<
235
+ O, //
236
+ OR extends OptRequired,
237
+ C extends MapCardinalityIllustrated
238
+ > = C extends MapCardinality.OneToMany | "I -> O[]"
37
239
  ? OR extends "opt"
38
240
  ? O[]
39
241
  : [O, ...O[]]
40
- : D extends MapDirection.OneToOne | "I -> O"
242
+ : C extends MapCardinality.OneToOne | "I -> O"
41
243
  ? OR extends "opt"
42
244
  ? O | null
43
245
  : O
44
- : D extends MapDirection.ManyToOne | "I[] -> O"
246
+ : C extends MapCardinality.ManyToOne | "I[] -> O"
45
247
  ? OR extends "opt"
46
248
  ? O | null
47
249
  : O
@@ -50,7 +252,8 @@ export type MapOutput<O, OR, D extends MapDirectionVal> = D extends
50
252
  /**
51
253
  * **MapTo<I, O>**
52
254
  *
53
- * A mapping function between an input type `I` and output type `O`.
255
+ * A mapping function between an input type `I` and output type `O`. Defaults to using
256
+ * the _default_ OneToMany mapping config.
54
257
  *
55
258
  * **Note:** this type is designed to guide the userland mapping; refer
56
259
  * to `MapFn` if you want the type output by the `mapFn()` utility.
@@ -58,16 +261,22 @@ export type MapOutput<O, OR, D extends MapDirectionVal> = D extends
58
261
  export type MapTo<
59
262
  I,
60
263
  O,
61
- IR extends OptRequired = "req",
62
- D extends MapDirectionVal = MapDirection.OneToMany,
63
- OR extends OptRequired = "opt"
64
- > = IR extends "opt"
65
- ? (source?: MapInput<I, IR, D>) => MapOutput<O, OR, D>
66
- : (source: MapInput<I, IR, D>) => MapOutput<O, OR, D>;
67
-
68
- export type MapFnOutput<I, O, S, OR extends OptRequired, D extends MapDirectionVal> = D extends
69
- | "I -> O[]"
70
- | MapDirection.OneToMany
264
+ C extends FinalizedMapConfig<
265
+ OptRequired,
266
+ MapCardinalityIllustrated,
267
+ OptRequired
268
+ > = DefaultOneToManyMapping
269
+ > = MapIR<C> extends "opt"
270
+ ? (source?: MapInput<I, MapIR<C>, MapCard<C>>) => MapOutput<O, MapOR<C>, MapCard<C>>
271
+ : (source: MapInput<I, MapIR<C>, MapCard<C>>) => MapOutput<O, MapOR<C>, MapCard<C>>;
272
+
273
+ export type MapFnOutput<
274
+ I,
275
+ O,
276
+ S,
277
+ OR extends OptRequired,
278
+ C extends MapCardinalityIllustrated
279
+ > = C extends "I -> O[]" | MapCardinality.OneToMany
71
280
  ? S extends I[]
72
281
  ? OR extends "opt"
73
282
  ? O[]
@@ -75,7 +284,7 @@ export type MapFnOutput<I, O, S, OR extends OptRequired, D extends MapDirectionV
75
284
  : OR extends "opt"
76
285
  ? O[] | null
77
286
  : O[]
78
- : D extends MapDirection.OneToOne | "I -> O"
287
+ : C extends MapCardinality.OneToOne | "I -> O"
79
288
  ? S extends I[]
80
289
  ? OR extends "opt"
81
290
  ? O[]
@@ -83,7 +292,7 @@ export type MapFnOutput<I, O, S, OR extends OptRequired, D extends MapDirectionV
83
292
  : OR extends "opt"
84
293
  ? O | null
85
294
  : O
86
- : D extends MapDirection.ManyToOne | "I[] -> O"
295
+ : C extends MapCardinality.ManyToOne | "I[] -> O"
87
296
  ? S extends I[][]
88
297
  ? OR extends "opt"
89
298
  ? O[]
@@ -93,17 +302,17 @@ export type MapFnOutput<I, O, S, OR extends OptRequired, D extends MapDirectionV
93
302
  : O
94
303
  : never;
95
304
 
96
- export type MapFnInput<I, IR extends OptRequired, D extends MapDirectionVal> = D extends
305
+ export type MapFnInput<I, IR extends OptRequired, D extends MapCardinalityIllustrated> = D extends
97
306
  | "I -> O[]"
98
- | MapDirection.OneToMany
307
+ | MapCardinality.OneToMany
99
308
  ? IR extends "opt"
100
309
  ? I | I[] | undefined
101
310
  : I | I[]
102
- : D extends MapDirection.OneToOne | "I -> O"
311
+ : D extends MapCardinality.OneToOne | "I -> O"
103
312
  ? IR extends "opt"
104
313
  ? I | I[] | undefined
105
314
  : I | I[]
106
- : D extends MapDirection.ManyToOne | "I[] -> O"
315
+ : D extends MapCardinality.ManyToOne | "I[] -> O"
107
316
  ? IR extends "opt"
108
317
  ? I[] | I[][] | undefined
109
318
  : I[] | I[][]
@@ -121,16 +330,18 @@ export type MapFnInput<I, IR extends OptRequired, D extends MapDirectionVal> = D
121
330
  * ```
122
331
  * 2. Block:
123
332
  * ```ts
124
- * // maps inputs to outputs (filtering or splitting where approp)
333
+ * // maps inputs to outputs (filtering or splitting where appr.)
125
334
  * const out2 = m(inputs);
126
335
  * ```
127
336
  */
128
337
  export type MapFn<
129
338
  I,
130
339
  O,
131
- IR extends OptRequired = "req",
132
- D extends MapDirectionVal = MapDirection.OneToMany,
133
- OR extends OptRequired = "opt"
134
- > = IR extends "opt"
135
- ? <S extends MapFnInput<I, IR, D>>(source?: S) => MapFnOutput<I, O, S, OR, D>
136
- : <S extends MapFnInput<I, IR, D>>(source: S) => MapFnOutput<I, O, S, OR, D>;
340
+ C extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>
341
+ > = MapIR<C> extends "opt"
342
+ ? <S extends MapFnInput<I, MapIR<C>, MapCard<C>>>(
343
+ source?: S
344
+ ) => MapFnOutput<I, O, S, MapOR<C>, MapCard<C>>
345
+ : <S extends MapFnInput<I, MapIR<C>, MapCard<C>>>(
346
+ source: S
347
+ ) => MapFnOutput<I, O, S, MapOR<C>, MapCard<C>>;
@@ -1,4 +1,5 @@
1
1
  import { Alpha } from "../alphabetic/alpha-characters";
2
+ import { Keys } from "../Keys";
2
3
 
3
4
  /**
4
5
  * Extracts the _required_ keys in the object's type. You also may
@@ -12,6 +13,16 @@ export type RequiredKeys<T extends object, V extends any = any> = {
12
13
  : never;
13
14
  }[keyof T];
14
15
 
16
+ /**
17
+ * Extracts the intersecting/common keys to two objects
18
+ */
19
+ export type IntersectingKeys<
20
+ T extends Record<string, any> | readonly string[],
21
+ U extends Record<string, any> | readonly string[]
22
+ > = {
23
+ [K in keyof T]: K extends Keys<U> ? K : never;
24
+ }[keyof T];
25
+
15
26
  /**
16
27
  * Extracts the _optional_ keys in the object's type. You also may
17
28
  * optionally filter by the _value_ of the key.
@@ -1,3 +1,3 @@
1
- export type DictFromKv<T extends readonly Readonly<{ key: string; value: unknown }>[]> = {
1
+ export type DictFromKv<T extends readonly { key: string; value: unknown }[]> = {
2
2
  [R in T[number] as R["key"]]: R["value"];
3
3
  };
@@ -8,10 +8,7 @@ export type ExpectExtends<VALUE, EXPECTED> = EXPECTED extends VALUE ? true : fal
8
8
  */
9
9
  export type AssertExtends<VALUE, EXPECTED> = EXPECTED extends VALUE ? any : never;
10
10
 
11
-
12
- export type IfExtends<VALUE, EXPECTED> = EXPECTED extends VALUE ? VALUE : never;
13
-
14
11
  /**
15
- * Give a type `TValue` and a comparison type `TExtends`
12
+ * Give a type `TValue` and a comparison type `TExtends`
16
13
  */
17
- export type IfExtendsThen<VALUE, EXPECTED, THEN> = EXPECTED extends VALUE ? THEN : never;
14
+ export type IfExtendsThen<VALUE, EXPECTED, THEN> = EXPECTED extends VALUE ? THEN : never;
@@ -1,5 +1,4 @@
1
1
  import { DictFromKv } from "src/types/kv";
2
- import { Mutable } from "src/types/Mutable";
3
2
  import { Narrowable } from "src/types/Narrowable";
4
3
 
5
4
  /**
@@ -21,5 +20,5 @@ export function kvToDict<
21
20
  out[kv.key as keyof DictFromKv<T>] = kv.value;
22
21
  }
23
22
 
24
- return out as DictFromKv<Mutable<T>>;
23
+ return out as DictFromKv<T>;
25
24
  }
@@ -1,118 +1,155 @@
1
- import { MapDirectionVal, MapFn, MapFnInput, MapTo } from "src/types/dictionary";
1
+ import {
2
+ FinalizedMapConfig,
3
+ MapCardinalityIllustrated,
4
+ MapFnInput,
5
+ MapperApi,
6
+ MapTo,
7
+ AsFinalizedConfig,
8
+ MapConfig,
9
+ ConfiguredMap,
10
+ MapFnOutput,
11
+ MapIR,
12
+ MapCard,
13
+ MapOR,
14
+ } from "src/types/dictionary";
2
15
  import { OptRequired } from "src/types/literal-unions";
3
16
  import { createFnWithProps } from "../createFnWithProps";
4
17
 
5
- export interface MapConfig<
6
- IR extends OptRequired = "req",
7
- D extends MapDirectionVal = "I -> O[]",
8
- OR extends OptRequired = "opt"
9
- > {
10
- input?: IR;
11
- output?: OR;
12
- direction?: D;
13
- }
14
-
15
18
  /**
16
- * Provides a mapper function using the default configuration
19
+ * utility function to take a fully-qualified _user_ config
20
+ * and make it into a FinalizedMapConfig
17
21
  */
18
- export type MapperApiDefault = <I, O>(map: MapTo<I, O>) => MapFn<I, O>;
19
-
20
- /**
21
- * Provides opportunity to configure _input_ and _output_ relationships
22
- * prior to providing a mapping function.
23
- */
24
- export type MapperApiConfigured = <
25
- IR extends OptRequired = "req",
26
- D extends MapDirectionVal = "I -> O[]",
27
- OR extends OptRequired = "opt"
22
+ const toFinalizedConfig = <
23
+ IR extends OptRequired,
24
+ D extends MapCardinalityIllustrated,
25
+ OR extends OptRequired
28
26
  >(
29
27
  config: MapConfig<IR, D, OR>
30
- ) => <I, O>(map: MapTo<I, O, IR, D, OR>) => MapFn<I, O, IR, D, OR>;
28
+ ) => {
29
+ return { ...config, finalized: true } as FinalizedMapConfig<IR, D, OR>;
30
+ };
31
+
32
+ export const DEFAULT_ONE_TO_MANY_MAPPING = toFinalizedConfig({
33
+ input: "req",
34
+ output: "opt",
35
+ cardinality: "I -> O[]",
36
+ });
37
+ export const DEFAULT_ONE_TO_ONE_MAPPING = toFinalizedConfig({
38
+ input: "req",
39
+ output: "req",
40
+ cardinality: "I -> O",
41
+ });
42
+ export const DEFAULT_MANY_TO_ONE_MAPPING = toFinalizedConfig({
43
+ input: "req",
44
+ output: "req",
45
+ cardinality: "I[] -> O",
46
+ });
47
+
48
+ export type DefaultOneToManyMapping = typeof DEFAULT_ONE_TO_MANY_MAPPING;
49
+ export type DefaultOneToOneMapping = typeof DEFAULT_ONE_TO_ONE_MAPPING;
50
+ export type DefaultManyToOneMapping = typeof DEFAULT_MANY_TO_ONE_MAPPING;
31
51
 
32
52
  /**
33
53
  * The single implementation for all mapping
34
54
  */
35
55
  const mapper =
36
- <
37
- IR extends OptRequired = "req",
38
- D extends MapDirectionVal = "I -> O[]",
39
- OR extends OptRequired = "opt"
40
- >(
41
- config: MapConfig<IR, D, OR> = {}
42
- ) =>
43
- <I, O>(map: MapTo<I, O, IR, D, OR>) => {
44
- // TODO
45
- config = {
46
- input: "req",
47
- output: "opt",
48
- direction: "I -> O[]",
49
- ...config,
50
- } as Required<MapConfig<IR, D, OR>>;
51
-
52
- const fn = <S extends MapFnInput<I, IR, D>>(source?: S) => {
56
+ <C extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>>(config: C) =>
57
+ <I, O>(map: MapTo<I, O, C>) => {
58
+ return <S extends MapFnInput<I, MapIR<C>, MapCard<C>>>(
59
+ source?: S
60
+ ): MapFnOutput<I, O, S, MapOR<C>, MapCard<C>> => {
61
+ /**
62
+ * Determine whether input is an array; this will be true
63
+ */
53
64
  const isArray =
54
- config.direction === "I -> O[]" && Array.isArray(source)
65
+ config.cardinality === "I -> O[]" && Array.isArray(source)
55
66
  ? true
56
- : config.direction === "I[] -> O" && Array.isArray(source) && Array.isArray(source[0])
67
+ : config.cardinality === "I[] -> O" && Array.isArray(source) && Array.isArray(source[0])
57
68
  ? true
58
69
  : false;
59
70
 
60
71
  if (isArray) {
61
- return (source as any).flatMap(map);
72
+ // iterate over inputs with flatMap to return mapped values as
73
+ // well as supporting filtering functionality. We could achieve
74
+ // the same results by simply passing in all inputs to our mapper
75
+ // in most cardinalities but when cardinality is M:1 we need to
76
+ // make sure that the first array of elements is passed as a single
77
+ // item and this approach achieves this.
78
+ // TODO: we should check that the approach below doesn't work for M:1 here
79
+ // as well
80
+ return (source as any).flatMap(map) as MapFnOutput<I, O, S, MapOR<C>, MapCard<C>>;
62
81
  } else {
63
- return map(source as any);
82
+ // receive _all_ inputs provided as pass into ; this is just a single input unless the
83
+ // cardinality is
84
+ return map(source as any) as MapFnOutput<I, O, S, MapOR<C>, MapCard<C>>;
64
85
  }
65
86
  };
66
-
67
- return fn as unknown as MapFn<I, O, IR, D, OR>;
68
87
  };
69
88
 
89
+ /**
90
+ * Takes a userland configuration and a default configuration and then produces
91
+ * the appropriately typed `ConfiguredMap` API surface.
92
+ */
93
+ const setMapper = <
94
+ U extends MapConfig<
95
+ OptRequired | undefined,
96
+ MapCardinalityIllustrated | undefined,
97
+ OptRequired | undefined
98
+ >,
99
+ D extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>
100
+ >(
101
+ config: U = { input: undefined, output: undefined, cardinality: undefined } as U,
102
+ defaultValue: D
103
+ ): ConfiguredMap<AsFinalizedConfig<U, D>> => ({
104
+ map: (source) => {
105
+ // merge userland config with defaults for a cardinality
106
+ const c = {
107
+ ...defaultValue,
108
+ ...config,
109
+ } as unknown as AsFinalizedConfig<U, D>;
110
+ return mapper(c)(source);
111
+ },
112
+ input: config?.input || defaultValue.input,
113
+ output: config?.output || defaultValue.output,
114
+ cardinality: config?.cardinality || defaultValue.cardinality,
115
+ });
116
+
70
117
  /**
71
118
  * **mapTo** _utility_
72
119
  *
73
- * This utility creates a strongly typed data mapper which maps from one
74
- * known source `I` to another `O`:
120
+ * This utility -- by default -- creates a strongly typed 1:M data mapper which maps from one
121
+ * known source `I` to any array of another `O[]`:
75
122
  * ```ts
76
123
  * const mapper = mapTo<I, O>(i => [{
77
124
  * foo: i.bar
78
125
  * }]);
79
126
  * ```
80
127
  */
81
- export const mapToFn = <I, O>(map: MapTo<I, O>) => {
82
- return mapper()<I, O>(map);
128
+ export const mapToFn: ConfiguredMap<DefaultOneToManyMapping>["map"] = (map) => {
129
+ return mapper(DEFAULT_ONE_TO_MANY_MAPPING)(map);
83
130
  };
84
131
 
85
132
  /**
86
133
  * Provides a `config` method which allows the relationships between _inputs_
87
134
  * and _outputs_ to be configured.
88
135
  */
89
- export const mapToDict = {
90
- /** configure the relationship between the _inputs_ and _outputs_ */
91
- config: <
92
- IR extends OptRequired = "req",
93
- D extends MapDirectionVal = "I -> O[]",
94
- OR extends OptRequired = "opt"
95
- >(
96
- c: MapConfig<IR, D, OR> = { input: "req", output: "opt", direction: "I -> O[]" } as MapConfig<
97
- IR,
98
- D,
99
- OR
100
- >
101
- ) => ({
102
- /**
103
- * create your mapping with your recently setup configuration:
104
- * ```ts
105
- * const mapper = mapTo
106
- * .config({ ... })
107
- * .map<I, O>(i => [{
108
- * foo: i.bar
109
- * }]);
110
- * ```
111
- */
112
- map<I, O>(map: MapTo<I, O, IR, D, OR>): MapFn<I, O, IR, D, OR> {
113
- return mapper(c)(map);
114
- },
115
- }),
136
+ export const mapToDict: MapperApi = {
137
+ config(config) {
138
+ const c = { ...DEFAULT_ONE_TO_MANY_MAPPING, ...config };
139
+ return setMapper(c, DEFAULT_ONE_TO_MANY_MAPPING);
140
+ },
141
+ oneToOne(config) {
142
+ const c = { ...DEFAULT_ONE_TO_ONE_MAPPING, ...config };
143
+ return setMapper(c, DEFAULT_ONE_TO_ONE_MAPPING);
144
+ },
145
+ manyToOne(config) {
146
+ const c = { ...DEFAULT_MANY_TO_ONE_MAPPING, ...config };
147
+ return setMapper(c, DEFAULT_MANY_TO_ONE_MAPPING);
148
+ },
149
+ oneToMany(config) {
150
+ const c = { ...DEFAULT_ONE_TO_MANY_MAPPING, ...config };
151
+ return setMapper(c, DEFAULT_ONE_TO_MANY_MAPPING);
152
+ },
116
153
  };
117
154
 
118
155
  /**
@@ -120,5 +157,13 @@ export const mapToDict = {
120
157
  *
121
158
  * This utility creates a strongly typed data mapper which maps from one
122
159
  * known source `I` to another `O`.
160
+ *
161
+ * Signatures:
162
+ * ```ts
163
+ * const defMap = mapTo<I,O>( ... );
164
+ * const configured = mapTo.config({ output: "req" }).map<I,O>( ... );
165
+ * const one2one = mapTo.oneToOne().map<I,O>( ... );
166
+ * const many2one = mapTo.manyToOne().map<I,O>( ... );
167
+ * ```
123
168
  */
124
169
  export const mapTo = createFnWithProps(mapToFn, mapToDict);