我需要创建一个实现具有57个属性的接口的类(实际上,这是googleapi adminsdk模式)。 我想避免在创建类时重新键入整个接口定义。 在考虑使用传播运算符,但失败了
仅具有3个属性的示例:
interface myInt {
field1:string;
field2:string;
field3?:number;
}
class theClass implements myInt{
private theFields:myInt
constructor(data:myInt)
{
this.theFields = {{}, ...data} <---incorrect
}
}
答案 0 :(得分:1)
好吧,这里发生了一些事情。从界面开始:
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
的情况下,会生成一个构造函数,该函数从类型{{ 1}}本身。请注意,这需要type assertion进行编译,因为TypeScript无法将ES5样式的构造函数识别为T
可用。
new
这使您可以通过扩展function BaseClass<T extends object>() {
return (function(this: T, data: T) {
Object.assign(this, data);
} as any) as new (arg: T) => T; // need assertion
}
来轻松创建IsMyInt
:
BaseClass<MyInt>()
如果您需要为此类添加更多功能,可以这样做:
// this implements IsMyInt
class IsMyIntAutomatic extends BaseClass<MyInt>() {}
好的,希望能有所帮助。祝你好运!