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

TypeScript配置泛型未显式声明参数类型时key丢失问题如何解决?

问题根因

你的报错是TypeScript泛型参数的推断优先级导致的。原写法中create函数的两个泛型参数Clients/Users是并行推断的,当clients字段下的函数未显式声明参数类型时,TypeScript无法先完成Clients类型的推导,会直接将其默认为空类型,keyof Clients就变成了never,最终导致users的入参被推导为Record<never, any>。


基础问题解决方案

把create函数改为单泛型参数的写法,让TypeScript优先推导整个配置对象的结构,再从配置结构中反向提取clients的键类型,就能同时实现参数自动推断和clients类型提示:

// 固定的client入参类型可以抽出来复用
type ClientFnArg = { a: number, b: string }

function create<const T extends {
  clients: Record<string, (arg: ClientFnArg) => void>,
  users: Record<string, (container: Record<keyof T['clients'], any>) => void>
}>(_cfg: T) {
  // 内部逻辑如果需要类型,可以直接通过T['clients']、T['users']获取
}

修改后你的代码就可以正常运行:

create({
  clients: {
    test: ({a, b}) => { 
      // a自动推断为number,b自动推断为string,无需显式声明
      console.log(a, b) 
    },
  },
  users: {
    user1: (clients) => {
      clients.test // 不会报错,可正确识别test属性
    },
  }
})

新增commands类型问题解决方案

如果你需要commands中的入参自动匹配clients对应的实例类型(包括派生类),只需要额外提取clients中函数的返回值类型即可:

type ClientFnArg = { a: number, b: string }
// 从clients配置中提取每个client的返回值类型,生成容器类型
type ClientContainer<T extends Record<string, (...args: any[]) => any>> = {
  [K in keyof T]: ReturnType<T[K]>
}

function create<const T extends {
  clients: Record<string, (arg: ClientFnArg) => any>,
  commands: Record<string, (container: ClientContainer<T['clients']>) => void>
}>(_cfg: T) {
  // 内部实现逻辑
}

这种写法下,clients里每个方法返回的Client/派生类类型会被完整保留,commands的入参会自动匹配对应的实例类型,不会丢失派生类的独有属性。


内容的提问来源于stack exchange,提问作者WindBridges

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:09:01