Web Development
TypeScript
Subjective
Oct 04, 2025
How do you create a type that extracts all possible object paths?
Detailed Explanation
Object path extraction uses recursive conditional types with template literals to traverse object structure.
Basic Path Extraction:
type Paths = T extends object
? {
[K in keyof T]: K extends string
? T[K] extends object
? K | `${K}.${Paths}`
: K
: never;
}[keyof T]
: never;
type User = {
id: number;
profile: {
name: string;
address: {
street: string;
city: string;
};
};
hobbies: string[];
};
type UserPaths = Paths;
// 'id' | 'profile' | 'hobbies' | 'profile.name' | 'profile.address' | 'profile.address.street' | 'profile.address.city'
Advanced Path Extraction with Array Handling:
type PathsAdvanced = {
[K in keyof T]: K extends string
? T[K] extends (infer U)[]
? `${Prefix}${K}` | `${Prefix}${K}.${number}` | PathsAdvanced
: T[K] extends object
? `${Prefix}${K}` | PathsAdvanced
: `${Prefix}${K}`
: never;
}[keyof T];
type ComplexObject = {
users: {
id: number;
profile: {
name: string;
};
}[];
settings: {
theme: string;
};
};
type ComplexPaths = PathsAdvanced;
// 'users' | 'settings' | 'users.0' | 'users.0.id' | 'users.0.profile' | 'users.0.profile.name' | 'settings.theme'
Type-Safe Get Function:
type PathValue =
P extends `${infer K}.${infer Rest}`
? K extends keyof T
? PathValue
: never
: P extends keyof T
? T[P]
: never;
function get>(
obj: T,
path: P
): PathValue {
const keys = path.split('.');
let result: any = obj;
for (const key of keys) {
result = result?.[key];
}
return result;
}
// Usage with type safety
const user: User = {
id: 1,
profile: {
name: 'John',
address: {
street: '123 Main St',
city: 'New York'
}
},
hobbies: ['reading']
};
const name = get(user, 'profile.name'); // Type: string
const city = get(user, 'profile.address.city'); // Type: string
// const invalid = get(user, 'profile.invalid'); // Error!
Set Function Implementation:
function set>(
obj: T,
path: P,
value: PathValue
): T {
const keys = path.split('.');
let current: any = obj;
for (let i = 0; i < keys.length - 1; i++) {
current = current[keys[i]];
}
current[keys[keys.length - 1]] = value;
return obj;
}
// Usage
set(user, 'profile.name', 'Jane'); // Type-safe
// set(user, 'profile.name', 123); // Error: number not assignable to string
Benefits:
• Type-safe object property access
• Compile-time path validation
• Excellent autocomplete support
• Prevents runtime property access errors.
Discussion (0)
No comments yet. Be the first to share your thoughts!
Share Your Thoughts