История вопроса:
Многие библиотеки экосистемы JavaScript предоставляют только исходные js-файлы, не имея собственных типов. Для описания типов сторонних или кастомных библиотек, а также глобальных переменных, в TypeScript реализован специальный формат файлов с расширением .d.ts (declaration files). Они стали стандартом для обеспечения типовой информации и типовой безопасности в проектах поверх любых js-модулей.
Проблема:
Если типы для сторонних JS-модулей не определены, TypeScript вынужден трактовать такие импорты как any, а значит вы теряете все преимущества статической типизации: ошибки в вызовах, несуществующих полях, неправильных параметрах логически проходят компиляцию, и выявляются только после запуска кода. Также невозможно делать автодополнение и навигацию по типам.
Решение:
С помощью declaration files можно вручную описать типы для любого JS-кода: функции, классы, объекты, пространства имён и даже глобальные константы. Таким образом, проект остаётся типобезопасным вне зависимости от происхождения внешней библиотеки.
Пример кода:
// hello.d.ts declare module 'hello' { export function sayHello(name: string): string; } // app.ts import { sayHello } from 'hello'; sayHello('TypeScript'); // Тип безопасен
Ключевые особенности:
Можно ли объявлять реализацию функций напрямую в declaration-файле?
Нет, в declaration-файлах допускается только объявление структур и сигнатур, а не их реализация. Любые тела функций, конструкторов вызовут ошибку компиляции.
// Нельзя: declare function sum(a: number, b: number) { return a + b; }
Где искать типы для популярных npm-модулей, если их нет в исходном пакете?
В репозитории DefinitelyTyped (npm-пакет @types/<lib>): почти все популярные пакеты имеют актуальные тайпинги в виде отдельных npm-модулей.
Можно ли описывать глобальные переменные (не через import), используя d.ts-файл?
Да, через механизм ambient declarations, например, declare var VERSION: string;. Это удобно для описания window.X, глобальных констант и переменных.
** Негативный кейс В проекте используется JS-библиотека без тайпингов. Разработчики забыли про d.ts-файл и обращаются к API через any. Возникают баги при обновлении библиотеки: старые вызовы ломаются, но компилятор этого не замечает.
Плюсы:
Минусы:
** Позитивный кейс Разработан собственный d.ts-файл на текущую библиотеку, сигнатуры поддерживаются в актуальном состоянии, используется автодополнение и навигация IDE.
Плюсы:
Минусы: