TypeScript如何推断Handler记录中所有可能的泛型输出类型
问题根因
原函数泛型定义强制所有传入的Handler必须使用完全相同的I、O类型参数,传入多个输出类型不同的handler时,TS会尝试将所有handler收敛为统一类型,最终触发类型不兼容报错。
修复方案
将泛型参数改为直接捕获整个传入的handlers对象结构,再从对象结构中提取所有handler对应的输出类型组成联合类型,同时保留对传入值必须为Handler类型的约束:
type Handler<I, O> = { i: I, o: O, handler: (i: I) => O }; function handlerGroup<T extends Record<string, Handler<any, any>>>( handlers: T ): (key: keyof T) => T[keyof T]["o"] { return (key) => { const { i, handler } = handlers[key]; return handler(i); }; }
类型表现
- 传入单个handler时,返回函数的输出类型与单个handler的
O类型完全一致,和原有表现对齐 - 传入多个不同类型的handler时不会触发类型报错,返回函数的输出类型为所有handler的
O类型组成的联合类型 - 额外优化:返回函数的入参
key会被自动推断为传入对象的合法键联合,传入不存在的key时会直接触发类型报错,比原实现的string类型更安全
验证代码:
const handleT1: Handler<number, number> = { i: 1, o: 1, handler: (i) => i }; const handleT2: Handler<number, string> = { i: 1, o: "1", handler: (i) => i.toString() }; const group1 = handlerGroup({ T1: handleT1 }); // 推导类型: (key: "T1") => number const group2 = handlerGroup({ T2: handleT2 }); // 推导类型: (key: "T2") => string const group3 = handlerGroup({ T1: handleT1, T2: handleT2 }); // 推导类型: (key: "T1" | "T2") => number | string,符合预期
内容的提问来源于stack exchange,提问作者Eliya Cohen
相关产品推荐
相关产品推荐

