Skip to content

Instantly share code, notes, and snippets.

@ai
Created October 10, 2020 03:12
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 ai/3c58a27929298fef498c26d0decc4e83 to your computer and use it in GitHub Desktop.
Save ai/3c58a27929298fef498c26d0decc4e83 to your computer and use it in GitHub Desktop.
class Post {
title: string = ''
text: string = ''
}
class Group {
title: string = ''
roles: string = ''
}
class User {
login: string = ''
age: string = ''
group: Group = new Group()
posts: Post[] = []
}
type Class = new (...args: any) => any
type Fields<I extends InstanceType<Class>> = {
[key in keyof I]?: I[key] extends object[]
? boolean | Fields<I[key][0]>
: I[key] extends object
? boolean | Fields<I[key]>
: boolean
}
type DeepPick<I, F extends Fields<I>> = {
[key in keyof I]: I[key] extends object[]
? DeepPick<I[key][0], F[key]>[]
: I[key] extends object
? DeepPick<I[key], F[key]>
: F[key] extends true
? I[key]
: never
}
function useMap<K extends Class, F extends Fields<InstanceType<K>>> (
cls: K,
fields: F
): [false, DeepPick<InstanceType<K>, F>] | [true | null] {
return {} as any
}
const fields: Fields<User> = {
login: true
}
const [isLoading, user] = useMap(User, {
login: true,
group: {
title: true
},
posts: {
title: true
}
})
if (user) {
// Positive
user.login = 'a'
user.group.title = ''
user.posts.forEach(post => {
post.title = 'Test'
})
// Negative
user.age = 21
user.group.roles = ''
user.posts.forEach(post => {
post.text = 'Test'
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment