如何在打字稿中为通用参数添加“新的”约束?

时间:2018-10-09 19:01:10

标签: typescript generics type-constraints

我已经知道如何为函数参数(例如下面的foo函数的参数)添加“ newable”(即具有构造函数)约束,但是相同的技术不适用于泛型类型参数。

这是为什么以及如何解决?

enter image description here

type NoParameterCtor<T> = { new(): T }

function foo<T>(ctor: NoParameterCtor<T>) { }

interface Bar<T extends NoParameterCtor<T>> { }

class Zoo { }

foo(Zoo) 
// no compiler error

class Zar implements Bar<Zoo> { }
// Type 'Zoo' does not satisfy the constraint 'NoParameterCtor<Zoo>'

1 个答案:

答案 0 :(得分:2)

如评论中所述,T extends NoParameterCtor<T>是一个不寻常的约束,表示“ T是构造自身的新构造函数”。除非您试图描述自我复制的构造函数,否则这不是您的意思。

如果您只想让T是“任何可更新的”,则无需关心实例类型。假设您使用的是TS3.0或更高版本,尽管也可以使用unknown,但是可以使用any来表示任何类型。所以也许你想Bar成为

interface Bar<T extends NoParameterCtor<unknown>> { }

以下内容仍然无效:

class Zar implements Bar<Zoo> { } // error! 
// Zoo does not satisfy the constraint NoParameterCtor<unknown>

这是因为类型Zoo是不可更新的;它是Zoo类的实例类型。我不知道您是否对TypeScript中的the difference between named values and named types感到困惑,但如果您这样做的话,您会很好。简而言之,class Zoo {}引入了一个名为Zoo type ,它是该类的实例的类型,还引入了一个名为{{1}的 value 。 },即此类实例的构造函数。并且Zoo值的类型不是Zoo类型。要引用Zoo构造函数值的类型,您需要改用Zoo

typeof Foo

我还假设您已经剥离了class Zar implements Bar<typeof Zoo> { } // okay BarZar的内容,因为它们与此处无关。但要清楚一点,因为TypeScript使用structural typing,所以空接口几乎可以匹配所有内容。如果Zoo需要访问Bar的实例类型,则可以使用内置库类型别名InstanceType<>来获取它:

T

希望有帮助。祝你好运!