-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pick deep object properties #36783
Comments
It's virtually impossible that the definition of type FlatCompany = HybridDeepPick<Company, "id" | "name" | { "addressId": ["address", "id"] }>
/* type FlatCompany = {
id: number;
name: string;
addressId: number;
} */ The main problem I see with writing such a type right now is that using tuples to index arbitrarily far down into a type (see #12290) would require more support for circular types than currently exists (#26980). So anything that is built with today's TypeScript would either need to do something unsupported or have an explicit depth limit, and will be ugly either way. Here's one ugly way which walks down about six or seven levels at most, does nothing good with types containing index signatures or optional/readonly properties, does not prevent you from using bad nested keys (e.g., type Tail<T extends readonly any[]> =
((...x: T) => void) extends ((h: any, ...r: infer R) => void) ? R : never;
type DeepIdx<T, K extends readonly PropertyKey[]> = K extends [] ? T : K[0] extends keyof T ? DI0<T[K[0]], Tail<K>> : never;
type DI0<T, K extends readonly any[]> = K extends [] ? T : K[0] extends keyof T ? DI1<T[K[0]], Tail<K>> : never;
type DI1<T, K extends readonly any[]> = K extends [] ? T : K[0] extends keyof T ? DI2<T[K[0]], Tail<K>> : never;
type DI2<T, K extends readonly any[]> = K extends [] ? T : K[0] extends keyof T ? DI3<T[K[0]], Tail<K>> : never;
type DI3<T, K extends readonly any[]> = K extends [] ? T : K[0] extends keyof T ? DI4<T[K[0]], Tail<K>> : never;
type DI4<T, K extends readonly any[]> = K extends [] ? T : K[0] extends keyof T ? DI5<T[K[0]], Tail<K>> : never;
type DI5<T, K extends readonly any[]> = K extends [] ? T : K[0] extends keyof T ? DI6<T[K[0]], Tail<K>> : never;
type DI6<T, K extends readonly any[]> = K extends [] ? T : K[0] extends keyof T ? DIX<T[K[0]], Tail<K>> : never;
type DIX<T, K> = never;
type DeepPick<T, K extends Record<keyof K, readonly PropertyKey[]>> =
{ [P in keyof K]: DeepIdx<T, K[P]> }
type AllKeys<T> = T extends any ? keyof T : never;
type HybridDeepPick<T, K extends (keyof T) | Record<keyof K, readonly PropertyKey[]>> =
DeepPick<T, { [P in Extract<K, PropertyKey> | AllKeys<Extract<K, object>>]:
P extends K ? [P] : Extract<K, { [Q in P]: any }>[P]
}> So make of that what you will. Good luck! |
👆 Once we ship commonly-used aliases, touching them in any way at all is guaranteed to produce a huge number of confusing breaks, which is why we've tried to stop doing so except when absolutely necessary. |
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
Search Terms
pick, nested, deep
Suggestion
Pick
can only be used to access properties at the top level of an object, it should support paths to get at more deeply nested values.Use Cases
Typing form inputs from GraphQL fragments
Examples
You could then construct a new type as follows:
type FlatCompany = Pick<Company, "id" | "name" | { "addressId": ["address", "id"] }>
Which would yield:
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: