Файлы объявлений TypeScript
Файл объявлений — этопереводчик между TypeScript и библиотеками JavaScript, который сообщает TypeScript, какие функции предоставляет библиотека JavaScript, какие типы у параметров и какие типы у возвращаемых значений.
Начнём с проблемы.
Предположим, вы пишете проект на TypeScript и вам нужно подключить стороннюю библиотеку JavaScript (например, jQuery). Вы можете написать такой код:
$('#foo');
// или
jQuery('#foo');
Этот код прекрасно работает в чистом проекте JavaScript, но в файле TypeScript он сразу вызовет ошибку:
jQuery('#foo');
// index.ts(1,1): error TS2304: Cannot find name 'jQuery'.
Почему возникает ошибка? Потому что TypeScript не распознаёт$иjQueryчто это такое.
Основная особенность TypeScript — проверка типов: ему нужно знать тип каждой переменной и каждой функции во время компиляции. Но jQuery — это чистая библиотека JavaScript без информации о типах, поэтому TypeScript, естественно, не может её понять.
Быстрое решение: ключевое слово declare
Самый простой способ — использовать ключевое словоdeclare, чтобы вручную сообщить TypeScript: «Эта переменная существует, и её тип таков»:
declare var jQuery: (selector: string) => any;
jQuery('#foo');
Смысл этой строки кода таков: объявить переменнуюjQuery, которая является функцией, принимающей параметр типаstring, а возвращаемое значение может быть любого типа (any)。
Теперь TypeScript не будет сообщать об ошибке, потому что компилятор уже знает, какой тип у jQuery.
declareТипы, объявленные с помощью ключевого слова, действуют только на этапе компиляции; они полностью удаляются из скомпилированного кода JavaScript и не влияют на поведение во время выполнения.
Скомпилированный код JavaScript приведённого выше примера выглядит так:
jQuery('#foo');
Как видите, объявлениеdeclareисчезло, остался только фактический код вызова.
Ноdeclareможет решить только временную проблему отдельного файла. Если в библиотеке много методов и много классов, очевидно, нереально вручную писать declare в каждом файле. Здесь на помощь приходят файлы объявлений.
Файлы объявлений: решение раз и навсегда
Файл объявлений помещает все объявленияdeclareв один отдельный файл, и любой TypeScript-файл в проекте может ссылаться на него.
Соглашения об именовании файлов
Файлы объявлений единообразно используют.d.tsв качестве суффикса,dчто означает «declaration». Например:
example.d.ts
Базовый синтаксис
Синтаксис объявления модуля выглядит следующим образом:
declare module Module_Name {
}
В файле TypeScript используйте директиву с тремя слэшами, чтобы подключить файл объявлений:
/// <reference path = "example.d.ts" />
Директива с тремя слэшами — это специфичный для TypeScript синтаксис, используемый, чтобы сообщить компилятору о необходимости включить указанный файл объявлений во время компиляции.
Файлы объявлений для многих популярных сторонних библиотек (таких как jQuery, Lodash) уже поддерживаются сообществом и хранятся вDefinitelyTypedпроект. Вам просто нужно установить соответствующий пакет@types/xxxчерез npm, и вы сможете использовать его, не прописывая типы вручную.
Полный пример: создание файлов объявлений с нуля
Следующий полный пример демонстрирует весь процесс создания и использования файла объявлений.
Весь процесс включает следующие файлы:
| Файл | Назначение |
|---|---|
| CalcThirdPartyJsLib.js | Сторонняя библиотека JavaScript (чистый JS, без информации о типах) |
| Calc.d.ts | Файл объявлений (написан вручную, описывает типы библиотеки) |
| CalcTest.ts | Бизнес-код на TypeScript (ссылается на файл объявлений, вызывает библиотеку) |
| CalcTest.js | Скомпилированный результат (JS-файл, скомпилированный с помощью tsc) |
| example.html | Финальная страница, работающая в браузере |
Шаг 1: Создание сторонней библиотеки JavaScript
Предположим, у нас есть сторонняя библиотека, предоставляющая функциональность кумулятивного суммирования. Она использует пространство имёнExampleдля организации кода и предотвращения конфликтов имён переменных:
Код файла CalcThirdPartyJsLib.js:
// Это имитация сторонней библиотеки JavaScript
// Объявить переменную пространства имён Example (создать пустой объект, если она не существует)
var Example;
// Используйте немедленно вызываемое функциональное выражение (IIFE), чтобы инкапсулировать код и предотвратить утечку внутренних переменных в глобальную область видимости
(function(Пример) {
// Конструктор Calc, используемый для создания объектов калькулятора
var Calc = (function () {
function Calc() {
// Пока параметры инициализации не нужны; оставьте конструктор для будущего расширения
}
})
// Метод doSum: вычисляет сумму всех целых чисел от 0 до limit
// limit (обязательный): верхняя граница суммы включительно
// Пример: при limit=10 вычисляется 0+1+2+...+10 = 55
Calc.prototype.doSum = function (limit) {
var sum = 0;
for (var i = 0; i <= limit; i++) {
sum = sum + i;
}
return sum;
}
// Прикрепите конструктор Calc к пространству имён Example
// Таким образом, извне можно создавать экземпляры через new Example.Calc()
Example.Calc = Calc;
return Calc;
})(Example || (Example = {}));
// Внутренний код самотестирования библиотеки
var test = new Example.Calc();
Эта библиотека использует распространённый шаблон: немедленно вызываемое функциональное выражение (IIFE). Проще говоря, оно оборачивает код в функцию и сразу его выполняет, поэтому переменные, определённые внутри функции, не утекают наружу, что позволяет избежать конфликтов имён с другим кодом.
Шаг 2: Напишите файл декларации
Теперь у нас есть библиотека JS, но у неё нет информации о типах. Нам нужно создать файл декларации, который описывает только «форму» библиотеки — какие есть классы, какие есть методы, какие типы у параметров и возвращаемых значений — но не содержит никакой фактической логики кода:
Код файла Calc.d.ts:
// Это файл декларации; он содержит только информацию о типах и не содержит исполняемого кода
// Объявите модуль Example, соответствующий пространству имён Example в библиотеке JS
declare module Example {
// Объявите класс Calc, сообщая TypeScript, что этот класс можно создать с помощью new
export class Calc {
// Объявите метод doSum: принимает параметр number и возвращает number
// Примечание: здесь объявлена только сигнатура метода, без тела метода (фигурных скобок)
doSum(limit: number): number;
}
}
Самое большое различие между файлом объявления и обычным файлом .ts: файл объявления содержит только сигнатуры типов, без кода реализации. Он отвечает только на вопрос "как выглядит эта функция", а не "что делает эта функция".
Шаг 3: Используйте это в коде TypeScript
Теперь напишите бизнес-код. После подключения файла объявления вы можете использовать эту стороннюю JS-библиотеку так же, как нативную библиотеку TypeScript:
Код файла CalcTest.ts:
// Директива с тремя косыми чертами: указывает компилятору TypeScript включить файл объявления
/// <reference path = "Calc.d.ts" />
// Создайте экземпляр Calc; теперь TypeScript может правильно определить тип obj
var obj = new Example.Calc();
// obj.doSum("Hello"); // Ошибка компиляции! "Hello" — строка, но doSum требует аргумент типа number
console.log(obj.doSum(10)); // Правильный вызов: передайте 10, ожидается 55
Обратите внимание на эту закомментированную строку:
obj.doSum("Hello");
Если вы раскомментируете эту строку, TypeScript сообщит об ошибке во время компиляции, потому что файл объявления уже указывает, что doSum принимает только параметр типа number. Это проверка типов защищает вас — ошибки выявляются во время написания кода, а не приводят к сбою во время выполнения в браузере.
Шаг 4: Компиляция TypeScript
Используйте встроеннуюtscкоманду для компиляции:
tsc CalcTest.ts
После компиляции будет сгенерированCalcTest.jsфайл со следующим содержимым:
Скомпилированный вывод CalcTest.js:
/// <reference path = "Calc.d.ts" />
var obj = new Example.Calc();
//obj.doSum("Hello"); // Ошибка компиляции
console.log(obj.doSum(10)); // Вывод: выводит 55 в консоль
Видно, что директивы с тройной косой чертой и информация о типах в файлах объявлений исчезли из скомпилированного вывода, оставив только чистый код времени выполнения JavaScript.
Шаг 5: Запуск в браузере
Наконец, создайте HTML-страницу, чтобы связать все JS-файлы вместе:
Пример
<html>
<head>
<meta charset="utf-8">
<title>Пример руководства (example.com)</title>
<!-- Шаг 1: Загрузите стороннюю библиотеку, чтобы сделать пространство имён Example доступным глобально -->
<script src = "CalcThirdPartyJsLib.js"></script>
<!-- Шаг 2: Загрузите скомпилированный бизнес-код -->
<script src = "CalcTest.js"></script>
</head>
<body>
<h1>Тест файла объявлений</h1>
<p>Давайте попробуем.</p>
</body>
</html>
Откройте этот HTML-файл в браузере, откройте консоль (F12), и вы увидите вывод:
55
Это возвращаемое значение doSum(10): 0+1+2+...+10 = 55.

Итог
Файл объявлений — это по сути «руководство по типам», которое позволяет TypeScript понимать и проверять чистые библиотеки JavaScript.
Весь рабочий процесс можно свести к трём шагам:
1. Получите JS-библиотеку и проанализируйте, какие API она предоставляет.
2. Напишите.d.tsфайл декларации, описывающий сигнатуры типов этих API.
3. Ссылайтесь на файл декларации в коде TypeScript, чтобы получить полную защиту проверки типов.
Другие расширенияДля часто используемых сторонних библиотек в повседневной разработке у подавляющего большинства уже есть готовые файлы деклараций (устанавливаются с помощьюnpm install @types/xxx). Только когда вы используете очень малоизвестную библиотеку или внутреннюю приватную библиотеку, вам нужно вручную писать файлы деклараций.