簡體   English   中英

在 Typescript 中,如何推斷模板文字中使用的 keyof 索引訪問類型

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM