Reputation: 3197
I have this type:
type Requests = {
"/endpoint": {
POST: {
body: any
response: any
}
// ...
}
// ...
}
I want to map response
to another value, but I get an error in vscode:
export type API = {
[route in keyof Requests]: {
[method in keyof Requests[route]]: {
body: Requests[route][method]["body"] // 🚨 Type '"body"' cannot be used to index type 'Requests[route][method]'
response: Requests[route][method]["response"] | { error: any } // 🚨 Type '"request"' cannot be used to index type 'Requests[route][method]'
}
}
}
Is there any way to accomplish this?
Upvotes: 4
Views: 660
Reputation: 186984
It appears typescript can't really generalize about any key that might be in that type, even though the list is finite and known. But it's easy to help it out.
If you specify the general format for the type:
type RequestsFormat = Record<string, { [key: string]: { body: any, response: any } }>
And then extend that:
interface Requests extends RequestsFormat {
"/endpoint": {
POST: {
body: any
response: any
}
}
}
Then typescript can figure out the rest.
Upvotes: -1
Reputation: 783
This should do what you want
type Requests = {
"/endpoint": {
POST: {
body: string
response: number
}
// ...
},
}
export type API = {
[route in keyof Requests]: {
[method in keyof Requests[route]]: {
body: Requests[route][method] extends { body: infer R } ? R : never
response: (Requests[route][method] extends { response: infer R } ? R : never) | { error: any }
}
}
}
Upvotes: 4