remeda
Version:
A utility library for JavaScript and Typescript.
1 lines • 5.27 kB
Source Map (JSON)
{"version":3,"file":"evolve.cjs","names":["purry","out: Record<string, unknown>"],"sources":["../src/evolve.ts"],"sourcesContent":["import type { IterableContainer } from \"./internal/types/IterableContainer\";\nimport { purry } from \"./purry\";\n\n/**\n * Basic structure of `evolver` parameter of the function `evolve`.\n */\ntype GenericEvolver = {\n readonly [P in string]: GenericEvolver | ((data: unknown) => unknown);\n};\n\n/**\n * Creates an assumed `evolver` type from the type of `data` argument.\n *\n * @example\n * interface Data {\n * id: number;\n * quartile: Array<number>;\n * time?: { elapsed: number; remaining?: number };\n * }\n * type Nested = Evolver<Data>; // => type Nested = {\n * // id?: ((data: number) => unknown) | undefined;\n * // quartile?: ((data: number[]) => unknown) | undefined;\n * // time?:\n * // | ((data: { elapsed: number; remaining?: number | undefined }) => unknown)\n * // | {\n * // elapsed?: ((data: number) => unknown) | undefined;\n * // remaining?: ((data: number) => unknown) | undefined;\n * // }\n * // | undefined;\n * // };\n */\ntype Evolver<T> = T extends object\n ? T extends IterableContainer\n ? never\n : {\n readonly [K in keyof T]?: K extends symbol\n ? never\n : Evolver<T[K]> | ((data: Required<T>[K]) => unknown);\n }\n : never;\n\n/**\n * Creates return type from the type of arguments of `evolve`.\n */\ntype Evolved<T, E> = T extends object\n ? {\n -readonly [K in keyof T]: K extends keyof E\n ? E[K] extends (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Functions aren't inferred correctly when using `unknown` for the params.\n ...arg: any\n ) => infer R\n ? R\n : Evolved<T[K], E[K]>\n : Required<T>[K];\n }\n : T;\n\n/**\n * Creates a new object by applying functions that is included in `evolver` object parameter\n * to the `data` object parameter according to their corresponding path.\n *\n * Functions included in `evolver` object will not be invoked\n * if its corresponding key does not exist in the `data` object.\n * Also, values included in `data` object will be kept as is\n * if its corresponding key does not exist in the `evolver` object.\n *\n * @param object - Object whose value is applied to the corresponding function\n * that is defined in `evolver` at the same path.\n * @param evolver - Object that include functions that is applied to\n * the corresponding value of `data` object at the same path.\n * @signature\n * R.evolve(data, evolver)\n * @example\n * const evolver = {\n * count: add(1),\n * time: { elapsed: add(1), remaining: add(-1) },\n * };\n * const data = {\n * id: 10,\n * count: 10,\n * time: { elapsed: 100, remaining: 1400 },\n * };\n * evolve(data, evolver)\n * // => {\n * // id: 10,\n * // count: 11,\n * // time: { elapsed: 101, remaining: 1399 },\n * // }\n * @dataFirst\n * @category Object\n */\nexport function evolve<T extends object, E extends Evolver<T>>(\n object: T,\n evolver: E,\n): Evolved<T, E>;\n\n/**\n * Creates a new object by applying functions that is included in `evolver` object parameter\n * to the `data` object parameter according to their corresponding path.\n *\n * Functions included in `evolver` object will not be invoked\n * if its corresponding key does not exist in the `data` object.\n * Also, values included in `data` object will not be used\n * if its corresponding key does not exist in the `evolver` object.\n *\n * @param evolver - Object that include functions that is applied to\n * the corresponding value of `data` object at the same path.\n * @signature\n * R.evolve(evolver)(data)\n * @example\n * const evolver = {\n * count: add(1),\n * time: { elapsed: add(1), remaining: add(-1) },\n * };\n * const data = {\n * id: 10,\n * count: 10,\n * time: { elapsed: 100, remaining: 1400 },\n * };\n * R.pipe(data, R.evolve(evolver))\n * // => {\n * // id: 10,\n * // count: 11,\n * // time: { elapsed: 101, remaining: 1399 },\n * // }\n * @dataLast\n * @category Object\n */\nexport function evolve<T extends object, E extends Evolver<T>>(\n evolver: E,\n): (object: T) => Evolved<T, E>;\n\nexport function evolve(...args: ReadonlyArray<unknown>): unknown {\n return purry(evolveImplementation, args);\n}\n\nfunction evolveImplementation(data: unknown, evolver: GenericEvolver): unknown {\n if (typeof data !== \"object\" || data === null) {\n return data;\n }\n\n const out: Record<string, unknown> = { ...data };\n\n for (const [key, value] of Object.entries(evolver)) {\n if (key in out) {\n out[key] =\n typeof value === \"function\"\n ? value(out[key])\n : evolveImplementation(out[key], value);\n }\n }\n\n return out;\n}\n"],"mappings":"wCAoIA,SAAgB,EAAO,GAAG,EAAuC,CAC/D,OAAOA,EAAAA,EAAM,EAAsB,EAAK,CAG1C,SAAS,EAAqB,EAAe,EAAkC,CAC7E,GAAI,OAAO,GAAS,WAAY,EAC9B,OAAO,EAGT,IAAMC,EAA+B,CAAE,GAAG,EAAM,CAEhD,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAQ,CAC5C,KAAO,IACT,EAAI,GACF,OAAO,GAAU,WACb,EAAM,EAAI,GAAK,CACf,EAAqB,EAAI,GAAM,EAAM,EAI/C,OAAO"}