Skip to content

Instantly share code, notes, and snippets.

@simonwep
Last active February 2, 2021 07:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simonwep/5d7b40e081b7689f3ab64d85ca83384b to your computer and use it in GitHub Desktop.
Save simonwep/5d7b40e081b7689f3ab64d85ca83384b to your computer and use it in GitHub Desktop.
Helper types to resolve selectables
interface User {
id: number;
userName: string;
fullName: string;
}
interface Comment {
id: number;
body: string;
author: User;
}
interface Post {
id: number;
author: User;
body: string;
content: string;
comments: Comment[];
}
type Selectable<T> = {
[P in keyof T]?:
T[P] extends Array<infer U> ? (Selectable<U> | boolean) :
T[P] extends object ? (Selectable<T[P]> | boolean) :
boolean;
}
type Select<T, Q extends Selectable<T>> = {
[P in keyof T as Q[P] extends boolean ? P : Q[P] extends object ? P : never ]:
// Property
Q[P] extends true ? T[P] :
// Array
T[P] extends Array<infer U> ? Select<U, Q[P]>[] :
// Object
T[P] extends object ? Select<T[P], Q[P]> : never
}
type SelectablePost = Selectable<User>;
type Selected = Select<Post, {
id: true;
author: {
fullName: true;
};
comments: {
body: true;
author: {
userName: true;
}
}
}>
const result: Selected = {
id: 1231,
author: {
fullName: "Hello world"
},
comments: {
body: "Foo",
author: {
userName: "Johnson"
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment