[英]In Typescript, how do I infer the keyof indexed access type used in a template literal
我有一個 REST api 接口,如下所示:
interface APIs {
artist: {
POST: { req: TypeA, resp: TypeB}
DELETE: { req: TypeC, resp: TypeD },
}
location: {
GET: { req: TypeE, resp: TypeF }
}
}
我想轉換為一組這樣的函數:
const server: Server<APIs> = {
postArtist: (req: TypeA) => TypeB,
deleteArtist: (req: TypeC) => TypeD,
getLocation: (req: TypeE) => TypeF,
}
我已經設法創建幾乎創建一個Server<T>
類型但是我無法引用POST
| DELETE
| 模板文字中使用的GET
鍵。 它們在下面顯示為key of T[Key]
,因此可以在右側使用?
是。
type Server<T> = {
[Key in keyof T as `${Lowercase<keyof T[Key] & string>}${Capitalize<Key & string>}`]: (req: T[Key][?]) => void
}
// |^=How to get this=^| and use it here -^^
如何引用用於生成 function 名稱的密鑰,以便我可以在右側引用它。
目前在${Lowercase<keyof T[Key] & string>}${Capitalize<Key & string>}
中, keyof T[Key]
會是一個並集,所以類型表達式會生成一個鍵的並集,導致所有結果中預設了子鍵。 如果我們只需要子鍵,這是一個很好的方法。
如果我們需要單獨處理每個子屬性,盡管我們應該使用另一個映射類型來單獨生成每個 function,然后將它們合並回結果中。 要將它們合並回單個 object 我們可以從這里使用UnionToIntersection
要提取請求和響應類型,最簡單的解決方案是使用條件類型:
interface RequestDefinition<TReq, TResp> {
req: TReq,
resp: TResp
}
type FromDefinition<T> =
T extends RequestDefinition<infer TReq, infer TResp>? (req: TReq) => TResp: never
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
type Server<T> = UnionToIntersection<{
[Key in keyof T]: {
[Http in keyof T[Key] as `${Lowercase<Http & string>}${Capitalize<Key & string>}`]: FromDefinition<T[Key][Http]>
}
}[keyof T]>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.