繁体   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