TypeScript泛型类实例推断为never的原因及默认泛型生效方案
问题1:实例tree被推断为
Tree<never>而非默认Tree<TreeRaw>的原因 TypeScript 泛型参数的默认值生效优先级低于基于入参的类型推断,触发逻辑是只有当完全无法从入参等位置推导得到泛型类型时,才会 fallback 到预设的默认值,此处的推导逻辑如下:
- 调用
new Tree([])时,空数组字面量[]的默认推断类型是never[] - 构造函数入参定义为
rawData: T[],TS会基于入参类型反向推导T的类型:T[] = never[]→ 推导得到T = never - 此时泛型
T已经有明确的推导结果,就不会再触发预设的TreeRaw默认值,因此实例类型被推断为Tree<never>
问题2:不手动传入泛型参数的调整方案
核心思路是调整构造函数入参的类型推断逻辑,让空数组场景下优先以TreeRaw作为泛型推导结果,修改方案如下:
interface TreeRaw { ID: string; parentID: string; seq: number; [props: string]: any; } class Tree<T extends TreeRaw = TreeRaw> { data: T[]; // 给入参设置默认值,同时指定默认值的类型为TreeRaw[],空入参/空数组场景下会优先基于该类型推导T constructor(rawData: T[] = [] as TreeRaw[]) { this.data = rawData; } } // 此时实例会被正确推断为Tree<TreeRaw> const tree = new Tree([]); // 不传参数的场景也能正确推断 const tree2 = new Tree();
修改后当你传入空数组或者不传参数时,TS会参考构造函数默认值的类型TreeRaw[]反向推导T为TreeRaw,不会再被空数组的默认never类型覆盖。
内容的提问来源于stack exchange,提问作者Viannnn
相关产品推荐
相关产品推荐

