Skip to content

Instantly share code, notes, and snippets.

@xxzefgh
Last active March 28, 2022 15:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xxzefgh/6552a646077c2f99844748a5fca23849 to your computer and use it in GitHub Desktop.
Save xxzefgh/6552a646077c2f99844748a5fca23849 to your computer and use it in GitHub Desktop.
type MapFn<T> = (x: T) => unknown;
type MapSchema<T> = { [K in keyof T]?: MapFn<T[K]> | MapSchema<T[K]> };
type MapReturnType<T, TMap extends MapSchema<T>> = {
[K in keyof T]: TMap[K] extends Function
? ReturnType<Extract<TMap[K], MapFn<T[K]>>>
: MapReturnType<T[K], TMap[K]>;
};
function isMapFn<T = any>(x: unknown): x is MapFn<T> {
return typeof x === "function";
}
function getKeys<T, K extends keyof T>(o: T): K[] {
return Object.keys(o) as any;
}
function mapProps<T, TMap extends MapSchema<T>>(
object: T,
mapSchema: TMap
): MapReturnType<T, TMap> {
const result: any = {};
const keys = getKeys(object);
for (const key of keys) {
const value = object[key];
let mappedValue: unknown;
if (mapSchema[key]) {
const fnOrSchema = mapSchema[key];
if (isMapFn(fnOrSchema)) {
mappedValue = fnOrSchema(value);
} else {
mappedValue = mapProps(value, fnOrSchema);
}
} else {
mappedValue = value;
}
if (mappedValue !== undefined) {
result[key] = mappedValue;
}
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment