Skip to content

Instantly share code, notes, and snippets.

@donabrams
Created May 27, 2019 16:23
Show Gist options
  • Save donabrams/89755018bef862c460683d384158b50c to your computer and use it in GitHub Desktop.
Save donabrams/89755018bef862c460683d384158b50c to your computer and use it in GitHub Desktop.
Typesafe get(obj, [keys...]
interface Example {
a: {
b: {
aNumber: number;
}
}
}
interface HasB {
b: {
aNumber: number;
}
}
const example: Example = { a: { b: { aNumber: 1 } } }
function get<A extends Object, K extends string>(obj: A, key: K): K extends keyof A
? A[K] : never;
function get<A extends Object, K1 extends string>(obj: A, keys: [K1]): K1 extends keyof A
? A[K1] : never;
function get<A extends Object, K1 extends string, K2 extends string>(obj: A, keys: [K1, K2]): K1 extends keyof A
? K2 extends keyof A[K1]
? A[K1][K2]
: never
: never;
function get<A extends Object, K1 extends string, K2 extends string, K3 extends string>(obj: A, keys: [K1, K2, K3]): K1 extends keyof A
? K2 extends keyof A[K1]
? K3 extends keyof A[K1][K2]
? A[K1][K2][K3]
: never
: never
: never;
function get(obj: any, keys: any) {
if (typeof keys === 'string') {
return obj[keys];
}
//else
return keys.reduce((obj: any, key: any) => {
return obj && obj[key] ? obj[key] : null;
}, obj);
}
const isObjWithB = get(example, 'a');
const isObjWithB2 = get(example, ['a']);
const isObjWithANumber = get(example, ['a', 'b']);
const isNumber = get(example, ['a', 'b', 'aNumber']);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment