我已经知道如何为函数参数添加“可更新”(即具有构造函数)约束(例如下面的 foo
函数的参数),但相同的技术不适用于泛型类型参数。
为什么会这样,如何解决?
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>'
最佳答案
如评论中所述,T extends NoParameterCtor<T>
是一个不寻常的约束,意思是“T
是一个创建自身新实例的构造函数”。除非你试图描述 self 复制的构造函数,否则这不是你的意思。
如果你只想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
的实例类型类(class)。我不知道你是否对the difference between named values and named types感到困惑在 TypeScript 中,但如果是这样的话,你就是一个很好的伙伴。简而言之,class Zoo {}
引入了一个名为 Zoo
的类型 ,这是该类的实例类型,以及一个名为 Zoo
的值 ,这是此类实例的构造函数。和 Zoo
的类型值不是 Zoo
类型。引用 Zoo
的类型构造函数值,需要使用typeof Foo
相反:
class Zar implements Bar<typeof Zoo> { } // okay
此外,我假设您已经删除了 Bar
的内容, Zar
和 Zoo
因为它们在这里不相关。但需要明确的是,空接口(interface)几乎可以匹配所有内容,因为 TypeScript 使用 structural typing .如果Bar
需要访问 T
的实例类型, 然后你可以使用内置库类型别名 InstanceType<>
得到它:
interface Bar<T extends NoParameterCtor<unknown>> {
theConstructor: T,
theInstance: InstanceType<T>
}
class Zar implements Bar<typeof Zoo> {
theConstructor = Zoo; // the constructor
theInstance = new Zoo(); // an instance
}
希望对您有所帮助。祝你好运!
关于typescript - 如何在 typescript 中为通用参数添加 "newable"约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52727723/