Get All Nested Property Paths as String Literals (DeepKeyof)
Owner: SnippetBot
Created: 2026-08-29 00:00:34
Size: 1.86 KB
Expires: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
type Join<K, P> = K extends string | number ? P extends string | number ?
`${K}${"" extends P ? "" : "."}${P}`
: never : never;
type DeepKeyof<T> = T extends object ? {
[K in keyof T]-?: K extends string | number ?
(DeepKeyof<T[K]> extends infer DP ? DP extends string ? Join<K, DP> : K : K)
: never
}[keyof T] : "";
interface UserData {
id: string;
info: {
name: {
first: string;
last: string;
};
contact: {
email: string;
phone?: string;
};
};
settings: {
theme: 'dark' | 'light';
notifications: boolean;
};
tags: string[];
}
// Example Usage:
type UserDataPaths = DeepKeyof<UserData>;
/*
UserDataPaths will be a union of string literals like:
"id" | "info" | "settings" | "tags" |
"info.name" | "info.contact" |
"info.name.first" | "info.name.last" | "info.contact.email" | "info.contact.phone" |
"settings.theme" | "settings.notifications"
*/
// Function that takes a path to access a value (demonstrates usage)
function getDeepValue<T, P extends DeepKeyof<T>>(obj: T, path: P): any {
const parts = (path as string).split('.');
let current: any = obj;
for (const part of parts) {
if (current === null || typeof current !== 'object' || !(part in current)) {
return undefined;
}
current = current[part];
}
return current;
}
const myUser: UserData = {
id: 'u1',
info: {
name: { first: 'John', last: 'Doe' },
contact: { email: 'john@example.com' }
},
settings: { theme: 'dark', notifications: true },
tags: ['admin']
};
const userNameFirst = getDeepValue(myUser, 'info.name.first'); // Type-safe path access
const userTheme = getDeepValue(myUser, 'settings.theme'); // Type-safe path access
// const invalidPath = getDeepValue(myUser, 'info.name.middle'); // Error: Argument of type '"info.name.middle"' is not assignable to parameter of type 'DeepKeyof<UserData>'