如何通过联合类型参数返回正确的动态类型?
错误原因与修复方案
错误原因
- 泛型T的条件类型是延迟解析的:
T extends A ? returnA : returnB只有在useFunc被具体调用(比如传入'a'或'b')时才会确定具体返回类型,但在函数定义阶段,编译器无法提前确认return 'type_a'或return 'type_b'是否匹配这个动态的条件类型。 - 类型窄化无法关联泛型:虽然通过
if (type == 'a')窄化了type的类型,但编译器无法将这种窄化关联到泛型T的条件判断上,因此无法验证返回值的类型兼容性。
修复方案
方案一:直接断言返回值为目标条件类型
明确告诉编译器返回值符合泛型条件类型,快速解决报错:
type A = 'a' type B = 'b' type returnA = 'type_a' type returnB = 'type_b' function useFunc<T extends A | B>(type: T = 'a' as T) { function resolveSomeByType(): T extends A ? returnA : returnB { if (type === 'a') { return 'type_a' as T extends A ? returnA : returnB } else { return 'type_b' as T extends A ? returnA : returnB } } return { resolveSomeByType } } // 测试用例 const { resolveSomeByType: resolveA } = useFunc('a') const resultA = resolveA() // 类型自动推断为returnA ('type_a') const { resolveSomeByType: resolveB } = useFunc('b') const resultB = resolveB() // 类型自动推断为returnB ('type_b')
方案二:使用函数重载
通过重载签名明确不同输入对应的返回类型,让编译器更准确地进行类型推断:
type A = 'a' type B = 'b' type returnA = 'type_a' type returnB = 'type_b' function useFunc<T extends A | B>(type: T = 'a' as T) { // 重载签名:对外暴露的类型逻辑 function resolveSomeByType(): T extends A ? returnA : returnB; // 实现签名:内部执行逻辑,类型放宽为联合类型 function resolveSomeByType(): returnA | returnB { if (type === 'a') { return 'type_a' } else { return 'type_b' } } return { resolveSomeByType } } // 测试用例 const { resolveSomeByType: resolveA } = useFunc('a') const resultA = resolveA() // 类型为returnA ('type_a') const { resolveSomeByType: resolveB } = useFunc('b') const resultB = resolveB() // 类型为returnB ('type_b')
方案三:使用类型映射表
定义输入类型到输出类型的映射关系,代码更简洁且扩展性更强:
type A = 'a' type B = 'b' // 定义输入与输出的类型映射 type TypeMap = { [A]: 'type_a', [B]: 'type_b' } function useFunc<T extends A | B>(type: T = 'a' as T) { function resolveSomeByType(): TypeMap[T] { // 利用类型断言让编译器确认返回值符合映射类型 return type === 'a' ? 'type_a' : 'type_b' as TypeMap[T] } return { resolveSomeByType } } // 测试用例 const { resolveSomeByType: resolveA } = useFunc('a') const resultA = resolveA() // 类型为'type_a' const { resolveSomeByType: resolveB } = useFunc('b') const resultB = resolveB() // 类型为'type_b'
内容的提问来源于stack exchange,提问作者user10666794
相关产品推荐
相关产品推荐

