Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | 1x 1x 5x 1x 19x 19x 11x 8x 7x 4x 7x 7x | import { isArray } from "@benneq/array";
import { isFunction, Mapper } from "@benneq/function";
type Primitive = string | null | number | boolean | undefined | bigint | symbol;
type DefFunction<I, T> = (value: I) => T;
type DefArray<I, T> = ReadonlyArray<MapperDefinition<I, T>>;
type DefObject<I, T> = {
[key in keyof T]: MapperDefinition<I, T[key]>;
};
type MapperDefinition<I, T> = T extends Primitive
? DefFunction<I, T>
: T extends ReadonlyArray<infer R>
? DefArray<I, R>
: DefObject<I, T>;
/**
*
* @example
* ```
* const valueMapper = mapper({
* a: [
* value => value.a.length,
* {
* a: value => value.a[0],
* z: value => value.a.at(-1)
* }
* ],
* B: value => value.b.toUpperCase()
* });
*
* const value = {
* a: [1,2,3],
* b: "b"
* };
*
* const mappedValue = valueMapper(value);
* console.log(mappedValue); // { a:[3,{a:1,z:3}], B: "B" }
* ```
*
* @param def
* @returns
*/
export const mapper =
<I, T>(def: MapperDefinition<I, T>): Mapper<I, T> =>
(initialValue) => {
if (isFunction(def)) {
return def(initialValue);
} else if (isArray(def)) {
return def.map((e) => mapper(e)(initialValue)) as T;
} else {
return (
Object.entries(def) as [keyof T, MapperDefinition<I, T[keyof T]>][]
).reduce((acc, [key, value]) => {
acc[key] = mapper(value)(initialValue);
return acc;
}, {} as T);
}
};
|