Skip to content

Instantly share code, notes, and snippets.

@rr-codes
Last active March 6, 2021 02:38
Show Gist options
  • Save rr-codes/9f4f905550af5e6eb3df4b831138fbca to your computer and use it in GitHub Desktop.
Save rr-codes/9f4f905550af5e6eb3df4b831138fbca to your computer and use it in GitHub Desktop.
/**
* Recursively maps values of an object
*
* @param object the target object
* @param transformation a mapping function, which is applied recursively to the deepest values
*/
function mapValues<O, K extends keyof O, R>(object: O, transformation: RecursiveTransform<O[K], R>): MappedObject<O, R> {
return Object.entries(object).reduce((prev, [key, value]) => {
prev[key] = typeof value === 'object' ? mapValues(value, transformation) : transformation(value);
return prev;
}, {} as any)
}
type MappedObject<O, R> = { [key in keyof O]: ResultValue<O, key, R>}
type RecursiveTransform<V, R> = (value: NestedValue<V>) => R
type NestedValue<V> = V extends {[p: string]: infer U}
? NestedValue<U>
: V
type ResultValue<O, K extends keyof O, R> = O[K] extends {[p: string]: infer U}
? { [key in keyof O[K]]: ResultValue<O[K], key, R>}
: R
// example
const foo = {
bar: 'hello',
baz: 1,
qux: {
a: 'a',
}
}
const result = mapValues(foo, (value) => typeof value === 'number' ? value : value.length)
// typeof result === { bar: number, baz: number, qux: { a: number } }
console.log(result)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment