Разница между статическими и экземплярами сторон классов

Я пытаюсь понять тему интерфейса в TypScript, когда я сталкивался с типом класса, я получил этот код из официальных документов

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

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

Я могу понять, что Clock не подходит для new (hour: number, minute: number); подписи new (hour: number, minute: number); поэтому мы получаем ошибку.

Но в документах объяснение - это то, что я не могу понять. Это происходит следующим образом:

Это связано с тем, что, когда класс реализует интерфейс, проверяется только сторона экземпляра класса. Поскольку конструктор находится в статической части, он не входит в эту проверку.

Любое объяснение будет оценено.

Ответ 1

Интерфейс объявляет метод/члены, которые имеют экземпляры, а не то, что имеет класс реализации.

Например, проверьте объявления Array и ArrayConstructor:

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". Типы конструктора свойств несовместимы. Тип 'Function' не присваивается типу '() => void'. Тип 'Функция' не соответствует сигнатуре '(): any'.

Ответ 2

Прежде чем вы сможете получить экземпляр, вам нужно использовать статическую сторону - constructor для получения экземпляра. В любом случае, вам не нужно new в вашем интерфейсе, ваш класс набрал себя, поэтому машинописный текст знает, какие аргументы он должен пройти по конструктору.

Вы можете использовать преимущества интерфейса с new типом, если хотите передать function или class который должен отвечать определенным требованиям конструктора, прежде чем он сможет быть создан.

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);

На самом деле, класс машинопись регулярная функция в JavaScript, который является статическим, когда вы не используете new перед ним. Это были документы, на которые ссылаются.

// static side
function Person() {

}

Person.SayHi = function () {
  return 'Hello';
}

console.log(Person.SayHi()); // static function..

var person = new Person() // instance side

См. Также этот ответ