Skip to content

Instantly share code, notes, and snippets.

@culttm
Created October 27, 2023 09:58
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 culttm/b9dbe31d77f74eacd0fd7909fd4f27f3 to your computer and use it in GitHub Desktop.
Save culttm/b9dbe31d77f74eacd0fd7909fd4f27f3 to your computer and use it in GitHub Desktop.
dot args types
type PathImpl<T, K extends keyof T> =
K extends string
? T[K] extends Record<string, any>
? T[K] extends ArrayLike<any>
? K | `${K}.${PathImpl<T[K], Exclude<keyof T[K], keyof any[]>>}`
: K | `${K}.${PathImpl<T[K], keyof T[K]>}`
: K
: never;
type Path<T> = PathImpl<T, keyof T> | keyof T;
type PathValue<T, P extends Path<T>> =
P extends `${infer K}.${infer Rest}`
? K extends keyof T
? Rest extends Path<T[K]>
? PathValue<T[K], Rest>
: never
: never
: P extends keyof T
? T[P]
: never;
declare function get<T, P extends Path<T>>(obj: T, path: P): PathValue<T, P>;
const object = {
firstName: "Diego",
lastName: "Haz",
age: 30,
projects: [
{ name: "Reakit", contributors: 68 },
{ name: "Constate", contributors: 12 },
]
} as const;
get(object, "firstName"); // works
get(object, "projects.0"); // works
get(object, "projects.0.name"); // works
get(object, "role"); // type error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment