【问题标题】:Typescript implements interface with 57 keys: use of spreadoperator?Typescript 使用 57 个键实现接口:使用扩展运算符?
【发布时间】:2019-05-22 20:06:49
【问题描述】:

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

【问题讨论】:

    标签: typescript class interface


    【解决方案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,生成一个构造函数,将属性从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&lt;MyInt&gt;() 轻松创建 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

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

    【讨论】:

    • 感谢您的出色回答。我开始开发工厂,你的帖子会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 2018-08-01
    • 2018-05-15
    • 2021-11-07
    • 2017-03-04
    • 2020-06-09
    相关资源
    最近更新 更多