TypeScript如何推断模板泛型参数避免重复类型声明
TypeScript 自动推断类泛型参数T的实现方案
问题场景
现有带value属性的树节点结构定义:
class Node<T> { public readonly value: T; constructor (value: T) { this.value = value; } // 其余节点相关方法 } class Container<U, N extends Node<T>, T> extends Node<U> { private children: N[]; public getChildrenValues(): T[] { return this.children.map((child) => child.value); } // 其余容器相关方法 }
当前实例化Container时必须重复传入T的类型,存在冗余:
// number类型需要重复书写两次 const x = new Container<string, Node<number>, number>();
目标是简化实例化写法,仅传入两个泛型参数,让TypeScript自动从N的类型中推导T:
const x = new Container<string, Node<number>>();
已尝试过在单个方法返回值中用infer提取T,但类中存在多个用到T的方法时,需要重复书写条件类型,维护成本高。
简洁实现方案
直接在类的泛型定义层完成T的推断,不需要在每个方法中重复写infer逻辑,只需要给泛型T设置基于N推导的默认值即可:
class Container<U, N extends Node<T>, T = N extends Node<infer V> ? V : never> extends Node<U> { private children: N[]; public getChildrenValues(): T[] { return this.children.map((child) => child.value); } // 所有需要用到T的方法可以直接引用T,不需要重复写类型判断 public getFirstChildValue(): T | undefined { return this.children[0]?.value; } }
逻辑说明
- 泛型约束
N extends Node<T>保留了类型校验能力,确保传入的节点类型符合要求 - 给
T设置默认值N extends Node<infer V> ? V : never,当实例化时不传入第三个泛型参数,TypeScript会自动根据传入的N类型提取对应的V作为T的实际类型 - 类内部所有位置都可以直接使用推导完成的
T类型,不需要重复编写条件类型逻辑
用法验证
// 两参数写法正常生效,T自动推断为number const numContainer = new Container<string, Node<number>>(); // numValues类型为number[],推导正确 const numValues = numContainer.getChildrenValues(); // 自定义Node子类也可以正常推导 class BooleanNode extends Node<boolean> {} const boolContainer = new Container<number, BooleanNode>(); // boolValues类型为boolean[],推导正确 const boolValues = boolContainer.getChildrenValues();
该方案要求TypeScript版本不低于4.0,低版本对泛型默认值的递归推断支持存在已知问题。
内容的提问来源于stack exchange,提问作者lishaak
相关产品推荐
相关产品推荐

