Typescript用57个按键实现接口:使用spreadoperator吗?

时间:2019-05-22 20:06:49

标签: typescript class interface

我需要创建一个实现具有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
   }
}

1 个答案:

答案 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>() {}

Link to this code

好的,希望能有所帮助。祝你好运!