【问题标题】:Difference between the static and instance sides of classes类的静态端和实例端之间的区别
【发布时间】:2016-09-07 06:34:52
【问题描述】:

我正在尝试理解 Typescript 中的界面主题 当我遇到Class type时,我从official docs得到了这段代码

interface ClockConstructor {
    new (hour: number, minute: number);
}

class Clock implements ClockConstructor {
    currentTime: Date;
    constructor(h: number, m: number) { }
}

我可以理解 Clock 与签名 new (hour: number, minute: number); 不匹配,这就是我们在此处收到错误的原因。

但在文档中,解释是我无法理解的。它是这样的:

这是因为当一个类实现一个接口时,只检查类的实例端。由于构造函数位于静态端,因此不包含在此检查中。

任何解释都将不胜感激。

【问题讨论】:

    标签: javascript typescript


    【解决方案1】:

    在获取实例之前,您需要使用静态端 constructor 来获取实例。无论如何,您的界面中不需要new,您的类是自己键入的,因此打字稿知道它必须通过构造函数传递的任何参数。

    如果您想传递必须满足特定构造函数要求的functionclass,则可以利用类型为new 的接口,然后才能对其进行实例化。

    interface IFoo {
       new(title: string);
    }
    
    function MyFunction(ctor: IFoo, title:string) {
       return new ctor(title);
    }
    
    class MyClass {
       constructor(public title: string) {}
    }
    
    class MySecondClass {
       constructor(public title: string) {}
    }
    
    var myClass = MyFunction(MyClass, 'title');
    var mySecondClass = MyFunction(MySecondClass, 'title');
    
    console.log(myClass.title, mySecondClass.title);
    

    实际上,TypeScript 类是 JavaScript 中的常规函数​​,当你不在它前面使用 new 时它是静态的。这是文档所指的。

    // static side
    function Person() {
    
    }
    
    Person.SayHi = function () {
      return 'Hello';
    }
    
    console.log(Person.SayHi()); // static function..
    
    var person = new Person() // instance side
    

    See also this answer

    【讨论】:

      【解决方案2】:

      接口声明实例拥有的方法/成员,而不是实现类拥有的。

      例如检查ArrayArrayConstructor 声明:

      interface Array<T> {
          length: number;
          toString(): string;
          toLocaleString(): string;
          push(...items: T[]): number;
          pop(): T | undefined;
          ...
          [n: number]: T;
      }
      
      interface ArrayConstructor {
          new (arrayLength?: number): any[];
          new <T>(arrayLength: number): T[];
          new <T>(...items: T[]): T[];
          (arrayLength?: number): any[];
          <T>(arrayLength: number): T[];
          <T>(...items: T[]): T[];
          isArray(arg: any): arg is Array<any>;
          readonly prototype: Array<any>;
      }
      

      如您所见,Array 具有存在于任何数组实例上的方法/成员:

      let a = [];
      a.push(1, 2, 3);
      console.log(a.length);
      

      但是ArrayConstructor 具有Array 本身存在的成员/方法:

      console.log(Array. prototype);
      console.log(Array.isArray(9));
      

      构造函数是“静态”部分的一部分,这就是它们在ArrayConstructor 中声明的原因。
      例如,如果您在接口上声明构造函数,那么实现该接口就会遇到问题:

      interface MyInterface {
          constructor();
          getName(): string;
      }
      
      class MyClass implements MyInterface {
          constructor() {}
      
          getName() { return "name" };
      }
      

      错误:

      类“MyClass”错误地实现了接口“MyInterface”。类型 属性“构造函数”不兼容。类型“功能”不是 可分配给类型 '() => void'。类型“功能”不匹配 签名 '(): any'。

      【讨论】:

        猜你喜欢
        • 2010-10-05
        • 2011-10-06
        • 2015-11-21
        • 2018-06-14
        • 1970-01-01
        • 2010-11-15
        • 1970-01-01
        • 2011-09-17
        相关资源
        最近更新 更多