返回扩展匿名类的函数的类型定义



我正在尝试创建一个函数,该函数将一个类作为参数(不是类实例,而是类本身(,并返回另一个扩展parameter中给定类的类。

我尝试如下定义typescript函数,但我得到了以下错误:Type 'typeof (Anonymous class)' is not assignable to type 'T'

function extendClass<T>(base: T): T  {
return class extends base{
};
}

我上面函数的示例用法:

class A {
}
const B = extendClass(A); // B is an extended class of A
let b = new B(); // b is instance of class B

extendClass函数的正确类型定义是什么??

您需要确保传递给extendClass的参数是一个类,而不是实例。在类型级别上,类可以表示为可更新函数:

new (...args: any[]) => any

为了使它更易读,让我们给它一个别名。

interface Constructable {
new (...args: any[]): any;
}

现在我们有了我们需要的一切!

function extendClass<T extends Constructable>(Base: T) {
return class extends Base {};
};

然而,手工编写返回类型有点麻烦,因为它需要同时处理返回类的类型和原型链。我们可以使用类型推理为我们做这项工作:

function extendClass<T extends Constructable>(BaseClass: T): typeof DerivedClass {
const DerivedClass = class extends BaseClass {};
return DerivedClass;
}

派生类被分配给一个局部变量,这样我们就可以读取和使用它的推断类型。

您需要指定T是一个构造函数,才能将其用作函数中注释类的基类。关于返回类型,我的建议是让编译器推断出这个类型。T

如果匿名类没有添加要从函数外部访问的成员,则可以使用T作为返回类型,但如果添加了成员,则让编译器进行推断。

function extendClass<T extends new (...a: any[])=> any>(base: T)  {
return class extends base{
};
}
class A {
}
const B = extendClass(A); // B is an extended class of A
type B = InstanceType<typeof B>
let b:B = new B(); // b is instance of class B

如果你没有添加公共成员,你可以使用T作为返回类型:

export function extendClass<T extends new (...a: any[]) => any>(base: T): T {
return class extends base {
}
}

如果您离开推断的版本并生成声明,您实际上可以看到如果我们向T:添加memeber,返回类型将如何显式声明

export function extendClass<T extends new (...a: any[]) => any>(base: T): {
new (...a: any[]): {
test(): void;
};
} & T {
return class extends base {
test() { }
}
}

您可以在代码中使用此类型,并且它应该按预期工作。

最新更新