Last active
June 30, 2021 17:30
-
-
Save imAliAzhar/0f68fcba4d7fdca02052e52758a68e15 to your computer and use it in GitHub Desktop.
A succint funtion that transforms JS Object to using a declarative schema
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Code | |
export const pickDeep = (obj: Dict<any>, key: string) => | |
hasKey(obj, key) ? obj[key] : key.split(".").reduce((o, k) => o?.[k], obj); | |
export const transform = (from: Dict<any>, to: Dict<any>) => | |
keys(to).reduce((o: Dict<any>, k) => { | |
const t = to[k]; // for each key that we want in the new object, get the transformer | |
o[k] = Array.isArray(t) // check if the transformer is an array | |
? typeof last(t) === "object" // if so, check if the last element of the transformer array is another 'to' object | |
? pickDeep(from, t[0]).map((i: Dict<any>) => transform(i, last(t))) // if so, apply this 'to' transformation to the array pointed in the first element of the transformer array | |
: last(t)(...t.slice(0, -1).map((u) => pickDeep(from, u))) // otherwise last element must be a function, pass it the values pointed in the transformer array | |
: isObject(t) // if transformer is another object | |
? transform(from, t) // recursively apply transform | |
: typeof t === "string" // if its a string | |
? pickDeep(from, t) // pick the deep value | |
: t; // otherwise just store the passed value as it is in the transformed object | |
return o; | |
}, {}); | |
// Usage | |
const source = { | |
user: { | |
id: 1, | |
first_name: "Ali", | |
last_name: "Azhar", | |
role: { | |
id: 1, | |
title: "Software Engineer", | |
}, | |
}, | |
}; | |
const transformer = { | |
user: { | |
// combine multiple values from source object | |
name: ["user.first_name", "user.last_name", (firstName: string, lastName: string) => `${firstName} ${lastName}`], | |
}, | |
role: "role.title", | |
}; | |
// Another example | |
{ | |
id: "id", | |
text: "question.text", | |
shortText: "question.text_short", | |
options: [ | |
"available_options", // transformation schema for an item within the list `available_options` | |
{ | |
id: "id", | |
text: "text", | |
subOptions: [ | |
"sub_options", // transformation schema for an item within the list `sub_options` | |
{ | |
id: "id", | |
text: "text", | |
subOptions: "sub_options", | |
}, | |
], | |
}, | |
], | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment