TypeScript条件类型返回值不可赋值报错修复方法
TypeScript入参关联返回值类型的报错修复
你在编写通过returnType入参推断返回类型的工具函数时出现TypeScript类型报错,报错信息如下:
原始实现代码:
type ReturnTypes = "string" | "date"; type StringOuput = string | undefined; type DateOutput = Date | undefined; type ObjectType<T> = T extends "string" ? StringOuput : T extends "date" ? DateOutput : never; function filterValue<T extends ReturnTypes>( returnType: ReturnTypes = "string" ): ObjectType<T> { switch (returnType) { case "date": return new Date(); default: return "s"; } } filterValue('string'); // 预期返回字符串值 filterValue('date') // 预期返回Date实例
报错核心原因
- 泛型参数与入参未绑定:入参
returnType被标注为联合类型ReturnTypes而非泛型T,TS无法从传入的实际参数推导泛型T的具体类型,也就无法匹配对应的条件返回类型。 - 泛型条件类型无法通过内部分支收窄:TS不会通过函数内部的
switch分支逻辑,自动证明分支返回值符合未确定的泛型条件类型ObjectType<T>,因此会提示返回值类型不匹配。
修复方案
方案1:修正泛型绑定(快速修复)
将入参类型修改为泛型T,内部返回值通过类型断言匹配泛型返回类型即可,逻辑正确性由分支判断保证:
type ReturnTypes = "string" | "date"; type StringOuput = string | undefined; type DateOutput = Date | undefined; type ObjectType<T> = T extends "string" ? StringOuput : T extends "date" ? DateOutput : never; function filterValue<T extends ReturnTypes>( // 入参类型改为T,默认值加断言适配泛型约束 returnType: T = "string" as T ): ObjectType<T> { switch (returnType) { case "date": return new Date() as ObjectType<T>; default: return "s" as ObjectType<T>; } } // 调用时类型推导正常 filterValue('string'); // 推导类型为string | undefined filterValue('date') // 推导类型为Date | undefined
方案2:函数重载(更推荐的最优写法)
这种入参与返回值一一映射的场景,用TS函数重载实现更简洁,不需要额外类型断言,TS会自动校验内部返回值与重载签名的匹配度,后续扩展类型也更方便:
type ReturnTypes = "string" | "date"; type StringOuput = string | undefined; type DateOutput = Date | undefined; // 重载签名:定义不同入参对应的返回类型 function filterValue(returnType?: "string"): StringOuput; function filterValue(returnType: "date"): DateOutput; // 实现签名:标注所有可能的入参和返回值联合类型 function filterValue(returnType: ReturnTypes = "string"): StringOuput | DateOutput { switch (returnType) { case "date": return new Date(); default: return "s"; } } // 调用时类型推导完全符合预期 const strRes = filterValue('string'); // 类型为string | undefined const dateRes = filterValue('date'); // 类型为Date | undefined const defaultRes = filterValue(); // 走默认参数,类型为string | undefined
重载写法的优势是内部逻辑不需要加任何强制类型断言,TS会自动校验每个分支的返回值是否符合对应类型,后续如果要新增返回类型(比如新增"number"对应number | undefined),只需要新增一条重载签名即可,维护成本更低。
内容的提问来源于stack exchange,提问作者retr0327
相关产品推荐
相关产品推荐

