Skip to content

Instantly share code, notes, and snippets.

@andyvanee
Last active May 22, 2025 15:02
Show Gist options
  • Save andyvanee/c3303de7225ee23c2d0359f6650b35bd to your computer and use it in GitHub Desktop.
Save andyvanee/c3303de7225ee23c2d0359f6650b35bd to your computer and use it in GitHub Desktop.
import type {ObjectLeafKeys} from '../ObjectLeafKeys';
type Expect<T, U> = T[] extends U[] ? (U[] extends T[] ? true : false) : false;
// jest always returns true, but type-checking will fail if T is false
const assert = <T extends true>() => {
return true as T;
};
describe('ObjectLeafKeys', () => {
it('infers the type of an object keys', () => {
const test = {
one: {
two: {three: 'string'},
four: 'string',
},
five: 'string',
};
type Result = ObjectLeafKeys<typeof test>;
type Expected = 'five' | 'one.four' | 'one.two.three';
expect(assert<Expect<Result, Expected>>()).toBe(true);
});
});
/**
* ObjectLeafKeys: Recursively enumerate all the leaf keys of an object
* @example
* type Test = {
* a: {
* b: { c: string; };
* d: string;
* };
* e: string;
* };
*
* type Result = ObjectLeafKeys<Test>;
* // Result = "a.b.c" | "a.d" | "e"
*/
export type ObjectLeafKeys<ObjectType extends object> = {
[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object
? `${Key}.${ObjectLeafKeys<ObjectType[Key]>}`
: `${Key}`;
}[keyof ObjectType & (string | number)];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment