在TypeScript中实现mixin而不使用任何类型
我正在与创建TypeScript代码的混搭程序争论:在TypeScript中实现mixin而不使用任何类型,typescript,mixins,Typescript,Mixins,我正在与创建TypeScript代码的混搭程序争论: function applyMixins(derivedCtor: Function, constructors: Function[]) { //Copies methods constructors.forEach((baseCtor) => { Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => { Ob
function applyMixins(derivedCtor: Function, constructors: Function[]) {
//Copies methods
constructors.forEach((baseCtor) => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
Object.defineProperty(
derivedCtor.prototype,
name,
Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||
Object.create(null)
);
});
});
//Copies properties
constructors.forEach((baseCtor) => {
let empty = new baseCtor();
Object.keys(empty).forEach((name) => {
Object.defineProperty(
derivedCtor.prototype,
name,
Object.getOwnPropertyDescriptor(empty, name) ||
Object.create(null)
);
});
});
}
它没有编译,抱怨这一行:let empty=new baseCtor()代码>:TS2351:此表达式不可构造。类型“Function”没有构造签名。
。我知道这可以通过将第一行中的函数
类型引用与任何
进行交换来解决,但我正试图在没有任何
的情况下生活,因为告诉TypeScript闭嘴通常是一种草率的方式
有没有一种方法可以在不使用any
的情况下实现此代码?问题是函数
是一种非常广泛的类型,包括任何函数,包括不能通过new
调用的函数。因此,编译器抱怨函数
不可构造。因此,解决方案是使用已知具有。在TypeScript中,这种签名通过在函数签名前加上关键字new
来表示:
type NewableFunctionSyntax = new () => object;
type NewableMethodSyntax = { new(): object };
这些类型都表示一个不接受任何参数的构造函数,并生成一个类型为assignableobject
的实例。注意,虽然这些语法不同,但本质上是相同的。(要了解这一点,请注意,编译器允许您多次声明var
,但如果您使用不同的类型对其进行注释,则会发出抱怨。事实上,以下编译器编译时没有错误
var someCtor: NewableFunctionSyntax;
var someCtor: NewableMethodSyntax; // no error
表示编译器将NewableFunctionSyntax
和NewableMethodSyntax
视为基本可互换。)
通过将函数
更改为以下选项之一,您的代码现在可以编译而不出错:
function applyMixins(derivedCtor: { new(): object }, constructors: { new(): object }[]) {
//Copies methods
constructors.forEach((baseCtor) => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
Object.defineProperty(
derivedCtor.prototype,
name,
Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||
Object.create(null)
);
});
});
//Copies properties
constructors.forEach((baseCtor) => {
let empty = new baseCtor();
Object.keys(empty).forEach((name) => {
Object.defineProperty(
derivedCtor.prototype,
name,
Object.getOwnPropertyDescriptor(empty, name) ||
Object.create(null)
);
});
});
}
让我们测试调用applyMixins()
,以确保我们了解{new():object}
的功能和不匹配之处:
class Works {
x = 1;
constructor() { }
}
applyMixins(Works, []); // okay
可以工作
很好,因为它是一个不带参数的类构造函数
class CtorRequiresArg {
y: string;
constructor(y: string) { this.y = y; }
}
applyMixins(CtorRequiresArg, []); // error!
// -------> ~~~~~~~~~~~~~~~
// Type 'new (y: string) => CtorRequiresArg'
// is not assignable to type 'new () => object'
CtorRequiresArg
失败,因为在构造字符串时必须传递一个string
参数,如new-CtorRequiresArg(“hello”)
。。。但是applyMixins()
只接受可以在没有任何参数的情况下调用的构造函数
最后:
function NotACtor() { }
applyMixins(NotACtor, []); // error!
// -------> ~~~~~~~~
// Type '() => void' provides no match
// for the signature 'new (): object'
NotACtor
失败,因为它被认为是不可构造的。这可能会令人惊讶,因为在运行时,没有任何东西会阻止您调用new notator()
,但编译器认为,如果您想要一个类构造函数,您应该在.ts
文件中使用class
表示法。。。即使是针对ES5运行时,因为TypeScript也会自动降低它的级别。(有关更多信息,请参阅)
函数
是不可构造的,而比如说,new()=>object
或{new():object}
是可构造的。对您的用例有效吗?如果是这样的话,我会在有机会的时候写一个答案。如果没有,请在问题文本中用相关示例详细说明。祝你好运谢谢,我添加了declare-type=new()=>object在模块中选择code>,然后使用类型
而不是函数
。但是与{new():object}
相比有什么区别?是否存在一个类型声明来捕获任何可构造性,而不仅仅是具有特定签名的可构造性?我尝试了new(…args:unknown[])=>object代码>,但这不允许构造函数具有特定类型的参数。使用new(…args:any[])=>对象代码>编译器不再抱怨了,但是我们使用的引用any
违背了我问题的目的。