You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复嵌套对象中函数参数的TypeScript类型约束错误?

如何修复嵌套对象中函数参数的TypeScript类型约束错误?

嘿,我来帮你搞定这个TypeScript类型问题!

你遇到的报错本质是:TypeScript没办法100%确定TApi[KEY][METHOD]一定是个可调用的函数——虽然我们肉眼能看到person和book下面的属性全是函数,但因为你用了as const把整个Api对象标记为只读,TypeScript在做类型推导时,会把这些属性的类型当成只读的函数类型,而Parameters这个工具类型要求输入必须严格符合(...args: any) => any的函数约束,所以就触发了类型不匹配的错误。

解决思路

我们需要给泛型METHOD加一个额外的约束,明确它只能是TApi[KEY]对象下对应值为函数的键名。这样TypeScript就能放心地把TApi[KEY][METHOD]当成函数来处理,Parameters工具类型也能正常提取参数类型了。

方案1:直接在泛型里加条件约束

修改你的executeApi函数泛型定义,给METHOD加上过滤条件:

const Api = {
  person: {
    find: (arg:{paramFind:string}) => {},
    create: (arg:{paramCreate:string}) => {},
    edit: (arg:{paramEdit:string}) => {},
    remove: (arg:{paramRemove:string}) => {}
  },
  book: {
    find: (arg:{paramFind:string}) => {},
    create: (arg:{paramCreate:string}) => {},
    edit: (arg:{paramEdit:string}) => {},
    remove: (arg:{paramRemove:string}) => {}
  }
} as const

type TApi = typeof Api

function executeApi<
  KEY extends keyof TApi,
  // 这里加了条件约束:只允许METHOD是TApi[KEY]下对应函数的键
  METHOD extends keyof TApi[KEY] & (TApi[KEY][METHOD] extends (...args: any[]) => any ? METHOD : never)
>(
  arg: {
    key: KEY,
    method: METHOD,
    // 现在Parameters能正常推导参数类型了
    param: Parameters<TApi[KEY][METHOD]>[0]
  }
) {
  // 你的缓存逻辑代码
  // 现在不需要as any断言了!
  return Api[arg.key][arg.method](arg.param)
}

// 测试调用完全正常,类型检查生效
executeApi({ key:'person', method: 'create', param: { paramCreate: 'John Doe' } })
executeApi({ key:'book', method: 'find', param: { paramFind: '1984' } })

方案2:用辅助类型提升可读性

如果觉得泛型里的条件约束太啰嗦,可以预先定义一个辅助类型,专门用来提取对象中值为函数的键名,后续还能复用:

const Api = {
  person: {
    find: (arg:{paramFind:string}) => {},
    create: (arg:{paramCreate:string}) => {},
    edit: (arg:{paramEdit:string}) => {},
    remove: (arg:{paramRemove:string}) => {}
  },
  book: {
    find: (arg:{paramFind:string}) => {},
    create: (arg:{paramCreate:string}) => {},
    edit: (arg:{paramEdit:string}) => {},
    remove: (arg:{paramRemove:string}) => {}
  }
} as const

type TApi = typeof Api

// 辅助类型:提取对象T中所有值为函数的键名
type FunctionKeys<T> = { 
  [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never 
}[keyof T]

function executeApi<
  KEY extends keyof TApi,
  METHOD extends FunctionKeys<TApi[KEY]> // 直接复用辅助类型
>(
  arg: {
    key: KEY,
    method: METHOD,
    param: Parameters<TApi[KEY][METHOD]>[0]
  }
) {
  // 缓存逻辑代码
  return Api[arg.key][arg.method](arg.param)
}

// 测试调用正常
executeApi({ key:'person', method: 'create', param: { paramCreate: 'John Doe' } })

这两种方案都能解决你的参数类型约束问题,而且还能去掉之前的as any断言,让类型检查更严格。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 06:49:30