如何在TypeScript类中同时实现回调函数的参数与返回值类型推断?
如何同时推断回调参数
v的类型与run()方法的返回值类型? 这是我上一篇帖子《Generic types in classes》的后续内容,该帖子已由@jcalz完美解答。在实践该方案后,我对TypeScript的类型推断逻辑产生了疑问,无法理清部分问题的原理。
我希望实现taskId到其回调函数的类型映射,并让run()方法返回类型化的结果。为此我搭建了如下最小示例:
type Task<T extends string> = { id: T; callback: (p?: any, v?: { [P in T]: any }) => any; }; // ---------------------- // 测试1:能推断回调参数v,但run()返回值为any // ---------------------- class InferCallbackParams<const T extends string> { public constructor(p: Task<T>[]) {} public run<K extends T>(id: K): ReturnType<Extract<Task<K>, {id: K}>["callback"]> {} } const t1 = new InferCallbackParams([ { id: "one", callback: (p, v) => { // v的类型被正确推断为:{ one: any; two: any } | undefined return 1; }, }, { id: "two", callback: (p, v) => { return "string"; } } ]); const r1 = t1.run("one") // r1的类型为any,不符合预期 // ---------------------- // 测试2:能推断run()返回值,但无法正确推断v的类型 // ---------------------- class InferCallbackReturnType<const T extends Task<string>> { public constructor(p: T[]) {} public run<K extends T["id"]>(id: K): ReturnType<Extract<T, {id: K}>["callback"]> { return "" as any } } const t2 = new InferCallbackReturnType([ { id: "one", callback: (p, v) => { // v的类型被推断为:{ [x: string]: any } | undefined,不符合预期 return 1; }, }, { id: "two", callback: (p, v) => { return "string"; } } ]); const r2 = t2.run("one") // r2的类型被正确推断为number
我发现当前的类泛型定义方式只能满足其中一个需求:
- 测试1的泛型
const T extends string能让构造函数正确推断回调参数v的类型,但run()方法的返回值始终是any; - 测试2的泛型
const T extends Task<string>能让run()方法正确推断返回值类型,但回调参数v的类型无法被正确限定为对应taskId的结构。
我推测原因在于:
- 当泛型定义为
const T extends Task<string>时,TypeScript仅会提取id的字符串字面量类型,而v的类型会被宽泛化为{ [x: string]: any }; - 当泛型定义为
const T extends string时,虽然能映射所有taskId,但Task<T>类型中回调函数的返回值被硬编码为any,导致run()无法推断具体返回类型。
请问是否存在方法可以同时实现两者:在构造类实例时,既让回调参数v获得正确的类型推断,又让run()方法返回对应回调的具体类型?
内容的提问来源于stack exchange,提问作者Flo Ragossnig
相关产品推荐
相关产品推荐

