能否定义Utility Type匹配抽象类的非抽象子类类型?
实现抽象类的非抽象子类类型匹配
完全可行,你可以通过TypeScript的条件类型和构造函数类型约束来定义NonAbstractDescendant类型,专门匹配抽象类的非抽象子类(类本身,而非实例)。
类型定义实现
// 定义非抽象构造函数类型:能创建实例的构造函数 type NonAbstractConstructor<T = {}> = new (...args: any[]) => T; // 定义抽象类的非抽象子类类型:接受抽象构造函数,返回对应的非抽象构造函数类型 type NonAbstractDescendant<T extends abstract new (...args: any[]) => any> = NonAbstractConstructor<InstanceType<T>>;
实际使用示例
abstract class A { abstract bar(): void; } // 符合要求的非抽象子类 class ConcreteA extends A { bar() { console.log("ConcreteA"); } } // 抽象子类(不符合要求) abstract class AbstractA extends A {} function b(type: NonAbstractDescendant<typeof A>) { // 可以直接实例化传入的类 const instance = new type(); instance.bar(); } // ✅ 合法:ConcreteA是A的非抽象子类 b(ConcreteA); // ❌ 报错:A本身是抽象类,不符合类型约束 // b(A); // ❌ 报错:AbstractA是抽象子类,不符合类型约束 // b(AbstractA);
原理说明
- TypeScript中,抽象类的构造函数类型签名是
abstract new (...args: any[]) => any,而非抽象类的构造函数是new (...args: any[]) => T,两者是不同的类型。 NonAbstractDescendant通过泛型约束T必须是抽象构造函数,然后返回NonAbstractConstructor<InstanceType<T>>,确保传入的构造函数必须能创建出A的实例,且本身不是抽象类。InstanceType<T>用来提取抽象类T的实例类型,保证子类的实例结构和父类一致。
内容的提问来源于stack exchange,提问作者Bruce Perens K6BP
相关产品推荐
相关产品推荐

