Skip to content

Instantly share code, notes, and snippets.

@arimariojesus
Last active October 9, 2022 23:16
Show Gist options
  • Save arimariojesus/691a048ea92de0a718eafc6b858f57d3 to your computer and use it in GitHub Desktop.
Save arimariojesus/691a048ea92de0a718eafc6b858f57d3 to your computer and use it in GitHub Desktop.
Get a deep property of an object. Receive a path in the form of a dot-separated string which sould ignore any value that is not a valid property in the object tree.
export const getDeepValue = <
T extends Record<string, any>,
K extends string = string,
>(
obj: T,
path: DeepKey<T, K> | DeepKey<T, K>[],
): DeepReturn<T, K> => {
const paths = Array.isArray(path) ? path : path.split('.');
return paths.reduce<DeepReturn<T, K>>((acc, curr) => {
return acc[curr];
}, obj as DeepReturn<T, K>);
};
type ValidValues = string | number | object | Array<any> | undefined | null;
export type DeepKey<
T extends Record<string, any>,
K extends string = string,
> = K extends keyof T
? T[K] extends ValidValues
? K
: never
: K extends `${infer TKey}.${infer Rest}`
? T[TKey] extends ValidValues
? DeepKey<Exclude<T[TKey], undefined>, Rest> extends never
? never
: K
: never
: never;
export type DeepReturn<T, K extends string = string> = K extends keyof T
? T[K]
: K extends `${infer TKey}.${infer Rest}`
? TKey extends keyof T
? DeepReturn<Exclude<T[TKey], undefined>, Rest>
: undefined
: undefined;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment