Skip to content

Instantly share code, notes, and snippets.

@nfrid
Created June 16, 2023 12:41
Show Gist options
  • Save nfrid/0decf68933c8681e07cdd2d0b497c921 to your computer and use it in GitHub Desktop.
Save nfrid/0decf68933c8681e07cdd2d0b497c921 to your computer and use it in GitHub Desktop.
Typescript helper types for working with nested object keys in dot notation (aka formik ass shit)
interface A {
foo: {
bar: number;
};
hee: {
hoo?: string;
haa?: {
test: number;
}[];
};
lol: boolean;
}
type T = NestedKeyOf<A>;
// ^? type T = "lol" | "foo.bar" | "hee.hoo" | "hee.haa" | "hee.haa.length" | `hee.haa.${number}.test`
type E1 = NestedObjectKeyType<A, 'foo.bar'>;
// ^? type E1 = number
type E2 = NestedObjectKeyType<A, 'hee.haa.3'>;
// ^? type E2 = { test: number;}[] | undefined
type E3 = NestedObjectKeyType<A, 'hee.haa.3.test'>;
// ^? type E3 = number
type DotPrefix<T extends string> = T extends '' ? '' : `.${T}`;
type NestedKeyOf<T extends object> = (
T extends object
? {
// @ts-ignore-next-line
[K in Exclude<keyof T, symbol>]: `${K}${DotPrefix<NestedKeyOf<T[K]>>}`;
}[Exclude<keyof T, symbol>]
: ''
) extends infer D
? Extract<D, string>
: never;
type NestedObjectKeyType<
T,
K extends string,
> = K extends `${infer P}.${infer R}`
? P extends keyof T
? T[P] extends Array<infer U>
? NestedObjectKeyType<U, R>
: NestedObjectKeyType<T[P], R>
: P extends `${number}`
? T extends Array<infer U>
? NestedObjectKeyType<U, R>
: NestedObjectKeyType<T, R>
: never
: K extends keyof T
? T[K]
: K extends `${number}`
? T
: never;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment