#typescript
#typescript
Вопрос:
У меня есть такой типаж:
type Requests = {
"/endpoint": {
POST: {
body: any
response: any
}
// ...
}
// ...
}
Я хочу сопоставить response
с другим значением, но я получаю сообщение об ошибке в 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]'
}
}
}
Есть ли какой-либо способ добиться этого?
Ответ №1:
Это должно делать то, что вы хотите
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 }
}
}
}
Комментарии:
1. Вау, вообще не знал о
infer
ключевом слове. Спасибо за это, это должно быть полезно для многих подобных проблем.2.В таком случае позвольте мне упомянуть, что существует распространенный трюк с использованием ключевого слова infer , который нигде не задокументирован. Вывод гораздо более эффективен в контексте функций, поэтому часто со сложными типами помогает добавить вспомогательный тип функции, так что, например, если я хочу получить тип хвоста кортежа, я могу сделать так.
type S<T extends any[]> = ((...args: T) => any) extends ((s: any, ...rest: infer R) => any) ? R : []
type W = S<[1, "it", "gets", "the", "rest"]>
Ответ №2:
Похоже, что typescript не может действительно обобщать какой-либо ключ, который может быть в этом типе, даже если список конечен и известен. Но с этим легко справиться.
Если вы укажете общий формат для типа:
type RequestsFormat = Record<string, { [key: string]: { body: any, response: any } }>
А затем расширьте это:
interface Requests extends RequestsFormat {
"/endpoint": {
POST: {
body: any
response: any
}
}
}
Затем typescript может разобраться с остальным.
Комментарии:
1. Это исправляет ошибку, но расширяет
keyof
тип дляRequests
tostring
. например, типRequests["asdf"]
не будет выдавать ошибку из-заRecord<string, ...>
типа.