Skip to content

Instantly share code, notes, and snippets.

@albertms10
Last active October 25, 2024 20:32
Show Gist options
  • Save albertms10/5a8b83e436a1689aa4b425ec22058301 to your computer and use it in GitHub Desktop.
Save albertms10/5a8b83e436a1689aa4b425ec22058301 to your computer and use it in GitHub Desktop.
TypeScript — all possible paths of an object
/**
* Object type that represents all possible paths of an object,
* including optional members.
* @template T The object type to get the paths from.
* @see https://stackoverflow.com/a/76131375/10851645
* @see https://gist.github.com/albertms10/5a8b83e436a1689aa4b425ec22058301
* @example
* interface Package {
* name: string;
* man?: string[];
* bin: { "my-program": string };
* funding?: { type: string; url: string }[];
* peerDependenciesMeta?: {
* "soy-milk"?: { optional: boolean };
* };
* }
*
* const list: Paths<Package>[] = [
* "name", // OK
* "man", // OK
* "bin.my-program", // OK
* "funding", // OK
* "funding.type", // OK
* "peerDependenciesMeta.soy-milk", // OK
* "peerDependenciesMeta.soy-milk.optional", // OK
* "invalid", // ERROR
* "bin.other", // ERROR
* ];
*/
export type Paths<T> = T extends Array<infer U>
? `${Paths<U>}`
: T extends object
? {
[K in keyof T & (string | number)]: K extends string
? `${K}` | `${K}.${Paths<T[K]>}`
: never;
}[keyof T & (string | number)]
: never;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment