Подтвердить что ты не робот

Какая разница между "объявить класс" и "интерфейс" в TypeScript

В TypeScript, при создании файлов описания источника .d.ts, что предпочтительнее и почему?

declare class Example {
    public Method(): void; 
}

или

interface Example {
    Method(): void;
}

Различия, которые я могу сказать, это то, что интерфейсы не могут иметь статические методы, поэтому для этого вы должны использовать класс. Оба не производят никакого выхода JS, поэтому, возможно, это не имеет значения?

4b9b3361

Ответ 1

interface - это когда вы просто хотите описать форму объекта. Нет никакого генерации кода для интерфейсов - они являются единственным артефактом в системе типов. Вы не увидите разницы в генерации кода для класса в зависимости от того, имеет ли он предложение implements.

declare class предназначен для того, чтобы описать существующий класс (обычно это класс TypeScript, но не всегда), который будет внешне присутствовать (например, у вас есть два файла .ts, которые скомпилируются до двух. js и оба включены через теги script на веб-странице). Если вы наследуете от class с помощью extends (независимо от того, был ли базовый тип declare class или регулярным class), компилятор должен сгенерировать весь код, чтобы подключить прототип цепи и пересылки конструкторов и что нет.

Если вы пытаетесь наследовать от declare class, который должен был быть интерфейсом, у вас будет ошибка времени выполнения, потому что этот сгенерированный код будет ссылаться на объект без проявления времени выполнения.

И наоборот, если вы просто implement интерфейс, который должен был быть declare class, вам придется повторно реализовать всех членов самостоятельно и не будет использовать преимущества повторного использования кода из потенциальный базовый класс и функции, которые проверяют цепочку прототипов во время выполнения, будут отклонять ваш объект, поскольку он фактически не является экземпляром базового класса.

Чтобы получить действительно упрямый, если у вас есть фон С++, вы можете приблизительно думать о interface как typedef и declare class как объявление extern конструктора, которому строго не хватает определения в этом компилируемом блоке.

С чистой стороны потребления (запись императивного кода, а не добавление новых типов) единственное различие между interface и declare class заключается в том, что вы не можете new интерфейса. Однако, если вы намерены использовать extend/implement один из этих типов в новом class, вам абсолютно необходимо правильно выбрать между interface и declare class. Только один из них будет работать.

Два правила, которые вам хорошо помогут:

  • Является ли имя выравнивания типа с конструкторской функцией (что-то invokable с new), которое действительно присутствует во время выполнения (например, Date есть, но JQueryStatic нет)? Если нет, вы определенно хотите interface
  • Я имею дело с скомпилированным классом из другого файла TypeScript или что-то достаточно похожее? Если да, используйте declare class

Ответ 2

Вы можете реализовать интерфейс:

class MyClass implements Example {
    Method() {

    }
}

В то время как синтаксис declare class действительно предназначен для использования для добавления определений типов для внешнего кода, который не написан в TypeScript, поэтому реализация является "в другом месте".

Ответ 3

В терминах непрофессионала declare используется в файлах .ts/d.ts, чтобы сообщить компилятору, что мы должны ожидать, что ключевое слово we declaring будет существовать в этой среде, даже если оно не определено в настоящий файл. Это позволит нам иметь безопасность типов при использовании объявленного объекта, поскольку компилятор Typescript теперь знает, что какой-либо другой компонент может предоставить эту переменную.