我正在try 创建严格类型的函数来调用我的API.我的 idea 是创建包含所有所需数据的文字,如下所示:

type ApiRoutes = {
  '/user': {
    POST: {
      payload: { mydata: number }
      response: UserData
    }
    DELETE: {
      payload: string
      response: UserData
    }
    GET: {
      payload: string
      response: UserData
    }
  }
}

在我的函数中使用它:

const apicall = async <
  E extends keyof ApiRoutes,
  T extends keyof ApiRoutes[E],
  P extends ApiRoutes[E][T]['payload]
>(
  endpoint: E,
  method: T,
  payload: P
):Promise<R extends ApiRoutes[E][T]['response> => {
  //do stuff
}

然后这样称呼它:

apicall('/user', 'POST', {mydata: 5})
apicall('/user', 'DELETE', 'my text')

我的问题是我弄错了

类型‘"PayLoad""不能用于索引类型’ApiRoutes[E][T]‘

但当我拨打apiCall时,我得到了正确的自动补全功能.你知道我需要改变什么吗?我有一个 idea ,推断关键字可能会有某种帮助,但我还没有玩它,所以我不知道如何接近它.

推荐答案

我不完全确定为什么会发生这种事.也许TS将方法的值视为泛型对象,而不是确切的对象(我必须承认这似乎是一种奇怪的行为),但正如您所指出的,您可以通过引入几个带有infer键的中间类型来修复它:

type Payload<E extends keyof ApiRoutes, T extends keyof ApiRoutes[E]> = ApiRoutes[E][T] extends {payload:infer P} ? P : never;
type Resp<E extends keyof ApiRoutes, T extends keyof ApiRoutes[E]> = ApiRoutes[E][T] extends {response:infer R} ? R : never;

您现在可以重写函数,如下所示:

const apicall = async <
  E extends keyof ApiRoutes,
  T extends keyof ApiRoutes[E],
  P extends Payload<E,T>
>(
  endpoint: E,
  method: T,
  payload: P
):Promise<Resp<E,T>> => {
  //do stuff
}

Typescript相关问答推荐

为什么从数组中删除一个值会删除打字错误?

对深度对象键/路径进行适当的智能感知和类型判断,作为函数参数,而不会触发递归类型限制器

打印脚本丢失函数的泛型上下文

如何在Reaction Query Builder中添加其他字段?

如何编写在返回函数上分配了属性的类型安全泛型闭包

重载函数的T helper参数

从子类集合实例化类,同时保持对Typescript中静态成员的访问

RXJS将对键盘/鼠标点击组合做出react

为什么&Quot;元素隐式具有';Any';类型,因为...即使我已经打字了,也不能作为索引显示错误吗?

我可以使用typeof来强制执行某些字符串吗

创建一个TypeScrip对象并基于来自输入对象的约束定义其类型

在打印脚本中将对象类型转换为数组

内联类型断言的工作原理类似于TypeScrip中的断言函数?

React中的效果挂钩在依赖项更新后不会重新执行

Typescript 确保通用对象不包含属性

使用受保护的路由和入门来响应路由

显式推断元组类型

使用 next.js 时Typescript 上的错误数据类型

TypeScript readonly 数组属性赋值错误

如何有条件地改变Angular Typescript 中的类型?