TypeScript递归类型函数错误返回never类型问题排查
问题分析与修正方案
是的,你写的这个Wow递归类型确实会返回never,但原因和你描述的略有不同——不是因为单元素数组时递归分支返回never,而是多次交叉带有同名value属性的对象时,不同字符串字面量类型的value会交叉出never类型。
具体逻辑链:
- 处理
Wow<['d']>时,结果是{value: 'd'} & {},也就是{value: 'd'},这一步正常。 - 处理
Wow<['c','d']>时,会变成{value: 'd'} & {value: 'c'},此时value的类型是'd' & 'c'——不同字符串字面量没有交集,结果为never,整个对象类型也就等价于never。 - 再往上递归,所有包含这个
never的交叉类型都会直接变成never,最终Wow<['a','b','c','d']>的结果自然是never。
修正方案1:返回包含所有可能value的联合类型对象
如果目标是得到所有元素对应的{value: 元素}的联合,把交叉&改成联合|即可:
import { List } from "ts-toolbelt"; type Wow<TArr extends string[]> = TArr['length'] extends 0 ? {} : { value: List.Last<TArr> } | Wow<List.Pop<TArr>>; type a = Wow<['a', 'b', 'c', 'd']>; // 类型为 { value: 'a' } | { value: 'b' } | { value: 'c' } | { value: 'd' }
修正方案2:生成嵌套结构
如果想要层级嵌套的对象(每个节点包含当前元素和下一层节点),调整为带next属性的嵌套类型:
import { List } from "ts-toolbelt"; type Wow<TArr extends string[]> = TArr['length'] extends 0 ? undefined : { value: List.Last<TArr>, next: Wow<List.Pop<TArr>> }; type a = Wow<['a', 'b', 'c', 'd']>; // 类型为 { value: 'd'; next: { value: 'c'; next: { value: 'b'; next: { value: 'a'; next: undefined } } } }
修正方案3:单value属性包含所有元素的联合
如果希望最终对象只有一个value属性,类型是数组所有元素的联合,直接用Union.ListOf提取联合类型即可,无需递归交叉:
import { List, Union } from "ts-toolbelt"; type Wow<TArr extends string[]> = { value: Union.ListOf<TArr> }; type a = Wow<['a', 'b', 'c', 'd']>; // 类型为 { value: 'a' | 'b' | 'c' | 'd' }
内容的提问来源于stack exchange,提问作者manwingbb
相关产品推荐
相关产品推荐

