泛型类类型推断困境:如何同时实现参数与返回类型推导?
问题描述
尝试在TypeScript泛型类中同时实现以下两个目标:
- 回调函数
cb的参数能访问对应id的字符串字面量类型 - 调用
get方法时能正确推断对应cb的返回类型
现有两种实现均存在缺陷:
- 第一种实现可正确推断
get方法的返回类型,但cb的参数无法获取id的具体字面量类型,仅能识别为{ [x: string]: any } - 第二种实现让
cb参数能拿到id的字面量类型,但get方法的返回类型退化为any
解决方案
通过优化泛型定义,将每个对象的id与cb参数类型强关联,同时让类的泛型保留数组中每个元素的具体字面量类型,即可同时满足两个需求。
完整实现代码
type MyObj<T extends string> = { id: T; cb: (p?: { [K in T]: any }) => unknown; } class MyClass<const T extends MyObj<string>[]> { constructor(p: T) {} get<K extends T[number]["id"]>(p: K): ReturnType<Extract<T[number], { id: K }>["cb"]> { return null as any; } } // 验证示例 const my = new MyClass([ { id: "foo", cb: (p) => { // p 的类型为 { foo?: any },可正确识别字面量 foo return "foo"; } }, { id: "bar", cb: (p) => { // p 的类型为 { bar?: any } return 1; } } ]); const r1 = my.get("foo"); // 类型推断为 string const r2 = my.get("bar"); // 类型推断为 number
核心要点
MyObj<T>中,cb的参数类型{ [K in T]: any }会根据T(即id的字符串字面量)生成专属的键类型,确保每个cb的参数仅对应自身的id- 类的泛型
const T extends MyObj<string>[]使用const断言,强制TypeScript保留数组中每个元素的字面量细节,避免类型自动拓宽 get方法通过Extract<T[number], { id: K }>精准筛选出对应id的对象类型,从而正确提取并推断cb的返回类型
内容的提问来源于stack exchange,提问作者Flo Ragossnig
相关产品推荐
相关产品推荐

