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'>
}
}
CodePudding user response:
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.