Что такое "*.d.ts" в TypeScript?
Я задался вопросом о файлах деклараций .d.ts
. Мне сказали, что файлы .d.ts
схожи с заголовочными файлами .h
в языках программирования C и C++, однако моя практика показала, что файлы .d.ts
не работают совсем одинаково. В данный момент я не понимаю, как правильно использовать файлы .d.ts
.
Похоже, что я не могу добавлять свои .js
или .ts
файлы в файлы .d.ts
, и единственный способ, чтобы мой проект работал, — это наличие всех трех типов файлов. У меня есть несколько вопросов:
Какова связь между этими тремя типами файлов?
Как я могу использовать файл
*.d.ts
? Значит ли это, что я могу навсегда удалить файл*.ts
?Если да, то как файл
*.d.ts
знает, какой файлJS
сопоставляется с ним?
5 ответ(ов)
Файл с расширением "d.ts" используется для предоставления информации о типах TypeScript для API, написанного на JavaScript. Идея заключается в том, что вы используете такие библиотеки, как jQuery или Underscore, которые уже существуют на JavaScript. Вам нужно использовать эти библиотеки в своем коде на TypeScript.
Вместо того чтобы переписывать jQuery, Underscore или любую другую библиотеку на TypeScript, вы можете создать файл с расширением d.ts, который будет содержать только аннотации типов. Затем, при написании кода на TypeScript, вы получите преимущества статической типизации, продолжая использовать библиотеку на чистом JS.
Это работает благодаря ограничению TypeScript, не позволяющему добавлять расширение ".ts" в конце оператора import
. Поэтому, когда вы ссылаетесь на какой-либо файл, например, my-module.js
, если рядом находится my-module.d.ts
, TypeScript подключит его содержимое:
src/
my-module.js
my-module.d.ts
index.ts
const thing = 42;
module.exports = { thing };
export declare const thing: number;
import { thing } from "./my-module"; // <- без расширения
// реализация `thing` используется из ".js"
console.log(thing); // 42
// объявление типа `thing` берется из ".d.ts"
type TypeOfThing = typeof thing; // number
При работе с проектом на JavaScript и использовании файлов .d.ts
я усвоил следующее.
Для того чтобы использовать файл .d.ts
для описания типов JavaScript, нужно, чтобы названия файлов .d.ts
совпадали с названиями файлов .js
. Каждый файл .js
должен находиться в одной директории с соответствующим ему файлом .d.ts
, который имеет то же имя. Код JS/TS, который нуждается в типах из файлов .d.ts
, должен ссылаться на эти файлы.
Например, если у вас есть файлы test.js
и test.d.ts
в папке testdir/
, вы можете импортировать их в компоненте React следующим образом:
import * as Test from "./testdir/test";
Файл .d.ts
экспортируется как пространство имен следующим образом:
export as namespace Test;
export interface TestInterface1{}
export class TestClass1{}
Таким образом, соблюдая эти правила, вы сможете правильно настроить типизацию вашего JavaScript-кода с помощью файлов .d.ts
.
Пример работы для конкретного случая:
Предположим, у вас есть my-module, который вы делитесь через npm.
Вы устанавливаете его командой npm install my-module
.
Используете его таким образом:
import * as lol from 'my-module';
const a = lol('abc', 'def');
Логика модуля вся находится в файле index.js
:
module.exports = function(firstString, secondString) {
// ваш код
return result;
}
Чтобы добавить аннотации типов, создайте файл index.d.ts
:
declare module 'my-module' {
export default function anyName(arg1: string, arg2: string): MyResponse;
}
interface MyResponse {
something: number;
anything: number;
}
Это позволит вашему модулю иметь типы, которые облегчат его использование в TypeScript.
Этот ответ предполагает, что у вас есть некоторый JavaScript-код, который вы не хотите преобразовывать в TypeScript, но хотите воспользоваться преимуществами проверки типов с минимальными изменениями в ваших файлах с расширением .js
.
Файл с расширением .d.ts
очень похож на заголовочный файл C или C++. Его цель — определить интерфейс. Вот пример такого файла:
mashString.d.ts
/** Усложняет чтение строки. */
declare function mashString(
/** Строка для сокрытия */
str: string
): string;
export = mashString;
mashString.js
// @ts-check
/** @type {import("./mashString")} */
module.exports = (str) => [...str].reverse().join("");
main.js
// @ts-check
const mashString = require("./mashString");
console.log(mashString("12345"));
В этой связи: mashString.d.ts
определяет интерфейс, mashString.js
реализует этот интерфейс, а main.js
использует его.
Для того чтобы проверить типы, добавьте // @ts-check
в ваши файлы с расширением .js
. Однако это проверяет только правильность использования интерфейса в main.js
. Чтобы также гарантировать, что mashString.js
реализует интерфейс правильно, мы добавляем /** @type {import("./mashString")} */
перед экспортом.
Вы можете создать первоначальные файлы .d.ts
, используя команду tsc -allowJs main.js -d
, а затем вручную отредактировать их для улучшения проверки типов и документации.
В большинстве случаев реализация и интерфейс имеют одно и то же имя, в данном случае mashString
. Но вы можете иметь различные реализации. Например, мы можем переименовать mashString.js
в reverse.js
и добавить альтернативный файл encryptString.js
.
Согласно официальной документации (https://www.typescriptlang.org/docs/handbook/2/type-declarations.html#dts-files):
.d.ts
файлы — это файлы декларации, которые содержат только информацию о типах. Эти файлы не генерируют .js выходные файлы; они используются только для проверки типов.
Как преобразовать строку в число в TypeScript?
Как динамически назначить свойства объекту в TypeScript?
Как конвертировать строку в enum в TypeScript?
Как удалить элемент массива в TypeScript?
Возможно ли расширять типы в TypeScript?