Skip to content

Instantly share code, notes, and snippets.

@dpchamps
Created June 17, 2021 06:38
Show Gist options
  • Save dpchamps/04605063e1f8c324375538c85d8c2456 to your computer and use it in GitHub Desktop.
Save dpchamps/04605063e1f8c324375538c85d8c2456 to your computer and use it in GitHub Desktop.
type Tuple<T = any> = readonly T[]
type Tail<T extends Tuple> = T extends readonly [any, ...infer U] ? U : []
type UnpackPath<T extends any, U extends Tuple> =
U[0] extends undefined ? T
: UnpackPath<
T[U[0]],
Tail<U>
>
type Split<T extends string, splitOn extends string = "", U extends Tuple<string> = []> =
T extends `${infer V}${splitOn}${infer Tail}` ? Split<Tail, splitOn, [...U, V]> :
T extends `${infer W}` ? [...U, W] :
never
declare function get<
T extends unknown,
U extends string,
V extends unknown = undefined
>(o: T, props: U, def?: V) : UnpackPath<T, Split<U, '.'>> & V extends never ? UnpackPath<T, Split<U, '.'>> : V;
// Demo
type SomeRichType = {
a: {
deeply: {
nested: {
prop: string,
}
}
},
something: {
with: {
anArray: ['a', 'b', 'c','d']
}
},
tagged: { prop: 'value1', name: "Micky" } | {prop: 'value2', name: "Donald"} | {prop: 'value3', name: "ShortStop"}
};
const x: SomeRichType = {} as any;
// Access properties, shallow and deep
const a = get(x, "a");
const b = get(x, "a.deeply");
const c = get(x, "a.deeply.nested.prop");
// Array access with numbers
const d = get(x, "something.with.anArray.1");
// Typed Default Vals
const defaultVal = get(x, "this.dont.exist", 10);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment