Разница между статическими и экземплярами сторон классов
Я пытаюсь понять тему интерфейса в 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
См. Также этот ответ