打字稿-扩展类的期望类型

时间:2019-04-03 17:33:05

标签: typescript

我需要创建一个函数,该函数期望任何类型的类都可以扩展另一个特定的类(类型,而不是实例)

Class A{}

foo(b: typeof 'extends A')

Class B extends A{}

Class C {}


foo(B) => working

foo(C) => not working

怎么办?

1 个答案:

答案 0 :(得分:2)

我想您可能对什么类型感到困惑。在foo(B)中,B不是类型;它是一个构造函数值。这种混淆非常普遍,可能是因为sometimes types and values can have the same name,例如当您声明class时。

无论如何,如果您的要求是foo()应该接受A实例的构造函数中的任何内容,则应执行以下操作:

class A { a: string = "A" }

declare function foo(ctor: new (...args: any[]) => A): void;

class B extends A { b: string = "B" }

class C { c: string = "C" }

foo(A); // okay
foo(B); // okay
foo(C); // error

类型new (...args: any[]) => A的意思是“任何产生类型A的实例的构造函数”。因此foo(B)之所以有效,是因为B是一个构造器,它生成类型为BA的{​​{3}})的实例。因此B确实产生了A实例,并且foo(B)起作用了。但是由于类型C不是A的子类型,因此foo(C)会产生错误。


我不知道您想在foo()的实现中做什么。如果要实际使用传入的构造函数,则可能应该考虑构造函数的参数是什么,并限制foo()仅接受支持这些参数的构造函数。例如,如果您期望foo()不带任何参数调用其构造函数,则可能应该限制它:

class A { a: string = "A" }

class B extends A { b: string = "B" }

class C { c: string = "C" }

// D's constructor requires a string argument
class D extends A { constructor(private d: string) { super(); } }

// ctor must be a no-arg constructor
declare function foo(ctor: new () => A): void;

foo(A); // still okay
foo(B); // still okay
foo(C); // still error
foo(D); // error

还要注意,具有subtype之类的空类是not recommended,即使是示例代码也是如此,因为TypeScript类型系统基于structures而不是names。由于class E {}class A {}具有相同的(空)结构,因此如果我保留这些类型,则调用class C {}不会出错。如有疑问,请为打算由编译器区别对待的类型添加不同的属性。

好的,希望能有所帮助;祝你好运!