嗯,这里发生了一些事情。从你的界面开始:
interface MyInt {
field1: string;
field2: string;
field3?: number;
}
你原来的类是持有MyInt,它并没有真正实现它。在课堂上持有MyInt 的“正确”方式是:
class HasMyInt {
private theFields: MyInt;
constructor(data: MyInt) {
this.theFields = { ...data }; // spread data into this.theFields
}
}
也许这对你来说就足够了,但是HasMyInt 本身并不是MyInt 接口的实例。如果您想创建一个作为实例的类,那么不幸的是,“正确”的方法确实涉及冗余属性声明,以及definite assignment assertions 以抑制--strictPropertyInitialization 的任何警告:
class IsMyIntManual implements MyInt {
// need these, unfortunately:
field1!: string;
field2!: string;
field3?: number;
constructor(data: MyInt) {
Object.assign(this, data); // spread data into this
}
}
这使用Object.assign() 而不是对象扩展运算符,因为它允许您修改现有目标对象 (this) 而不是返回一个新对象。
如果你真的想避免多余的属性声明,你可以创建一种“基类工厂”,给定对象类型T,生成一个构造函数,将属性从T类型的参数复制到本身。请注意,这需要 type assertion 进行编译,因为 TypeScript 无法将 ES5 样式的构造函数识别为 newable。
function BaseClass<T extends object>() {
return (function(this: T, data: T) {
Object.assign(this, data);
} as any) as new (arg: T) => T; // need assertion
}
这使您可以通过扩展 BaseClass<MyInt>() 轻松创建 IsMyInt:
// this implements IsMyInt
class IsMyIntAutomatic extends BaseClass<MyInt>() {}
如果你需要为这个类添加更多功能,你可以这样做:
class ExtendingIsMyInt extends BaseClass<MyInt>() {
public anotherProperty: number;
constructor(data: MyInt, anotherProperty: number) {
super(data);
this.anotherProperty = anotherProperty;
}
method() {
return this.field2 != this.field1 ? this.field3 || this.anotherProperty : 0;
}
}
Link to this code
好的,希望对您有所帮助。祝你好运!