Ответ 1
Этот ответ относится к TypeScript 1.8+. Есть много других ответов на этот вопрос, но все они, похоже, охватывают более старые версии.
Есть две части для продления прототипа в TypeScript.
Часть 1 - Объявить
Объявление нового элемента, чтобы он мог проходить проверку типов. Вам нужно объявить интерфейс с тем же именем, что и конструктор/класс, который вы хотите изменить, и поместить его под правильным объявленным пространством имен/модулем. Это называется увеличением объема.
Расширение модулей таким образом может быть выполнено только в специальном объявлении .d.ts
files *.
//in a .d.ts file:
declare global {
interface String {
padZero(length : number) : string;
}
}
Типы во внешних модулях имеют имена, которые включают кавычки, такие как "bluebird"
.
Имя модуля для глобальных типов, таких как Array<T>
и String
, равно global
без кавычек. Однако во многих версиях TypeScript вы можете полностью отказаться от объявления модуля и сразу объявить интерфейс, чтобы иметь что-то вроде:
declare interface String {
padZero(length : number) : string;
}
Это в некоторых версиях pre-1.8, а также в некоторых версиях post-2.0, таких как самая последняя версия, 2.5.
Обратите внимание, что вы не можете иметь ничего, кроме операторов declare
в файле .d.ts
, иначе это не сработает.
Эти объявления добавляются в объем окружения вашего пакета, поэтому они будут применяться во всех файлах TypeScript, даже если вы никогда не import
или ///<reference
файла напрямую. Однако вам все равно нужно импортировать реализацию, которую вы пишете во второй части, и если вы забудете сделать это, вы столкнетесь с ошибками во время выполнения.
* Технически вы можете пройти это ограничение и разместить объявления в обычных файлах .ts
, но это приводит к некоторому худшему поведению компилятора, и это не рекомендуется.
Часть 2 - Внедрение
Часть 2 фактически реализует элемент и добавляет его к объекту, в котором он должен существовать, как и в JavaScript.
String.prototype.padZero = function (this : string, length: number) {
var s = this;
while (s.length < length) {
s = '0' + s;
}
return s;
};
Обратите внимание на несколько вещей:
-
String.prototype
вместоString
, который является конструкторомString
, а не его прототипом. - Я использую явный
function
вместо функции стрелки, потому чтоfunction
будет правильно принимать параметрthis
, откуда он вызывается. Функция стрелки всегда будет использовать тот жеthis
, что и место, в котором оно было объявлено. Одно время, когда мы не хотим, чтобы это произошло, это расширение прототипа. - Явный
this
, поэтому компилятор знает типthis
, который мы ожидаем. Эта часть доступна только в TS 2.0+. Удалите аннотациюthis
, если вы компилируете для 1.8-. Без аннотацииthis
может быть неявно напечатанany
.
Импорт JavaScript
В TypeScript конструкция declare
добавляет элементы в область видимости, что означает, что они появляются во всех файлах. Чтобы убедиться, что ваша реализация из части 2 подключена, import
файл находится прямо в начале вашего приложения.
Вы импортируете файл следующим образом:
import '/path/to/implementation/file';
Без импорта ничего. Вы также можете импортировать что-то из файла, но вам не нужно импортировать функцию, определенную вами на прототипе.