如何让TypeScript泛型转换函数根据输入类型推导返回类型?
解决TypeScript泛型转换函数的类型匹配问题
问题核心
你尝试用条件类型实现泛型转换函数,但返回类型始终是联合类型,无法精准匹配输入对应的输出类型。问题根源在于两点:
- 函数参数类型写死为
Bases,而非绑定到泛型参数B,导致TypeScript无法捕获输入的具体子类型; - 未具体化的泛型条件类型会保留表达式形式,传入联合类型时直接展开为联合结果。
正确实现方案
方案1:函数重载(最直观易维护)
通过重载签名明确输入与输出的类型映射,TypeScript会自动根据输入匹配对应重载:
// 重载签名:定义输入输出的精准映射 function transformGeneric(base: BaseA): TransformedA; function transformGeneric(base: BaseB): TransformedB; // 兜底实现签名 function transformGeneric(base: Bases): Transformed | null; // 函数实现 function transformGeneric(base: Bases): Transformed | null { switch (base.type) { case "A": return transformA(base); case "B": return transformB(base); default: return null; } } // 类型推断正常 const transformedA = transformGeneric(baseASample); // 类型为TransformedA const transformedB = transformGeneric(baseBSample); // 类型为TransformedB
方案2:泛型+类型映射表(适合扩展更多类型)
用映射表明确输入类型到输出类型的对应关系,同时将参数类型绑定到泛型参数,让TypeScript精准推断:
// 定义输入类型到输出类型的映射表 type TransformMap = { A: TransformedA; B: TransformedB; }; // 修正后的泛型转换函数 const transformGeneric = <B extends Bases>(base: B): B extends { type: infer T } ? TransformMap[T] : null => { switch (base.type) { case "A": return transformA(base as BaseA) as any; case "B": return transformB(base as BaseB) as any; default: return null as any; } }; // 类型推断正常 const transformedA = transformGeneric(baseASample); // 类型为TransformedA const transformedB = transformGeneric(baseBSample); // 类型为TransformedB
这里的类型断言是因为TypeScript在switch分支中无法自动将base缩小到对应子类型,属于必要的辅助手段。
原代码问题解析
transformGeneric:返回类型直接写Transformed | null,丢失了具体子类型的精准信息;transformGeneric2:参数类型为Bases,泛型B未与参数绑定,条件类型无法根据输入收缩,最终返回联合类型;transformGeneric3:同样未将参数类型绑定到泛型,且条件分支仅处理了BaseA的情况,BaseB的返回类型仍为宽泛的Transformed。
内容的提问来源于stack exchange,提问作者michaelschufi
相关产品推荐
相关产品推荐

