Issue
We have 2 interfaces: File and User. 1 File has 1 User.
We want to pick data from the user and the file.
interface DownloadFile {
  id: string
  name: string
  user: User
  createdAt: Date
}
interface User {
  id: string
  name: string
  isEmailValidated: boolean
  unsubscribe: boolean
  email: string
}
type QueryResponse = {
  file: Pick<DownloadFile, 'id' | 'name'> & {
    user: Pick<DownloadFile['user'], 'id' | 'name' | 'email'>
  }
}
This is working fine.
How can we prevent a typo in the nested object name (userTYPO) and get an error:
type QueryResponse = {
  file: Pick<DownloadFile, 'id' | 'name'> & {
    userTYPO: Pick<DownloadFile['user'], 'id' | 'name' | 'email'>
  }
}
Solution
You need some construct to constrain the set of possibilities here. And if you want to constrain a type then you must use a generic type with that constraint. That means that this simple snippet:
type A = B & C
Isn't going to work because there is no way to constrain B and C.
So what you need is a type that makes this type for you.
There are a lot of ways to do this. Here's one.
type MakeFileUserQueryResponseType<
  T extends {
    fileKeys: keyof DownloadFile,
    userKeys: keyof DownloadFile['user'],
  }
> = {
  file: Pick<DownloadFile, T['fileKeys']> & {
    user: Pick<DownloadFile['user'], T['userKeys']>
  }
}
Which you would use like so:
type QueryResponse = MakeFileUserQueryResponseType<{
  fileKeys: 'id' | 'name',
  userKeys: 'id' | 'name' | 'email'
}>
You specifically require a strict type as constraint of T, and anything that fails to conform to that will be a type error.
Answered By - Alex Wayne
 
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.