Структуры библиотек
В общих чертах, способ структурирования вашего файла объявления зависит от того, как библиотека используется. Существует множество способов предоставления библиотеки для использования в JavaScript, и вам нужно написать файл объявления, соответствующий этому способу. Это руководство описывает, как определить распространенные шаблоны библиотек и как написать файлы объявления, которые соответствуют этому шаблону.
Каждый тип основного шаблона структурирования библиотек имеет соответствующий файл в разделе Шаблоны. Вы можете начать с этих шаблонов, чтобы ускорить работу.
Определение типов библиотек
Сначала мы рассмотрим типы библиотек, которые могут представлять файлы объявлений TypeScript. Мы кратко покажем, как используется каждый тип библиотеки, как она пишется, и перечислим некоторые примеры реальных библиотек.
Определение структуры библиотеки является первым шагом в написании ее файла объявления. Мы дадим подсказки о том, как определить структуру, основываясь на ее использовании и ее коде. В зависимости от документации и организации библиотеки один из них может быть проще другого. Мы рекомендуем использовать тот, который вам удобнее.
Что следует искать?
Вопросы, которые следует задать себе, рассматривая библиотеку, для которой вы пытаетесь создать типизацию.
-
Как получить библиотеку?
Например, можете ли вы получить ее только через npm или только с CDN?
-
Как ее импортировать?
Добавляет ли она глобальный объект? Использует ли она
requireилиimport/exportоператоры?
Небольшие примеры для разных типов библиотек
Модульные библиотеки
Практически все современные библиотеки Node.js относятся к семейству модулей. Эти типы библиотек работают только в среде JS с загрузчиком модулей. Например, express работает только в Node.js и должна загружаться с помощью функции CommonJS require.
ECMAScript 2015 (также известный как ES2015, ECMAScript 6 и ES6), CommonJS и RequireJS имеют схожие понятия импорта модуля. В JavaScript CommonJS (Node.js), например, вы бы написали
var fs = require("fs"); В TypeScript или ES6 ключевое слово import выполняет ту же функцию:
import * as fs from "fs";
Обычно в документации модульных библиотек вы увидите одну из этих строк:
var someLib = require("someLib"); или
define(..., ['someLib'], function(someLib) {
}); Как и в случае с глобальными модулями, вы можете увидеть эти примеры в документации модуля UMD, поэтому обязательно проверьте код или документацию.
Определение модульной библиотеки по коду
Модульные библиотеки обычно содержат по крайней мере некоторые из следующих элементов:
- Безусловные вызовы к
requireилиdefine - Объявления, такие как
import * as a from 'b';илиexport c; - Присваивания
exportsилиmodule.exports
Они редко содержат:
- Присваивания свойствам
windowилиglobal
Шаблоны для модулей
Доступны четыре шаблона для модулей: module.d.ts, module-class.d.ts, module-function.d.ts и module-plugin.d.ts.
Вы должны сначала прочитать module.d.ts для общего обзора их работы.
Затем используйте шаблон module-function.d.ts, если ваш модуль можно вызвать как функцию:
const x = require("foo");
// Note: calling 'x' as a function
const y = x(42); Используйте шаблон module-class.d.ts, если ваш модуль можно создать с помощью new.
const x = require("bar");
// Note: using 'new' operator on the imported variable
const y = new x("hello"); Если у вас есть модуль, который при импорте вносит изменения в другие модули, используйте шаблон module-plugin.d.ts:
const jest = require("jest");
require("jest-matchers-files"); Глобальные библиотеки
Глобальная библиотека — это библиотека, к которой можно получить доступ из глобальной области видимости (т. е. без использования каких-либо форм import). Многие библиотеки просто экспонируют одну или несколько глобальных переменных для использования. Например, если вы использовали jQuery, переменную $ можно использовать, просто обратившись к ней:
$(() => {
console.log("hello!");
}); Обычно в документации глобальной библиотеки приводятся указания о том, как использовать библиотеку в теге HTML-скрипта:
<script src="http://a.great.cdn.for/someLib.js"></script>
Сегодня большинство популярных глобально доступных библиотек на самом деле написаны как UMD-библиотеки (см. ниже). Документация UMD-библиотек трудно отличима от документации глобальных библиотек. Прежде чем писать файл объявления глобальной библиотеки, убедитесь, что библиотека на самом деле не является UMD.
Определение глобальной библиотеки по коду
Код глобальной библиотеки обычно очень прост. Глобальная библиотека «Привет, мир» может выглядеть так:
function createGreeting(s) {
return "Hello, " + s;
} или так:
// Web
window.createGreeting = function (s) {
return "Hello, " + s;
};
// Node
global.createGreeting = function (s) {
return "Hello, " + s;
};
// Potentially any runtime
globalThis.createGreeting = function (s) {
return "Hello, " + s;
}; При рассмотрении кода глобальной библиотеки вы обычно увидите:
- Операторы
varили объявленияfunctionна верхнем уровне - Одно или несколько присваиваний
window.someName - Предположение о существовании примитивов DOM, таких как
documentилиwindow
Вы не увидите:
- Проверки или использования загрузчиков модулей, таких как
requireилиdefine - Импорты в стиле CommonJS/Node.js в виде
var fs = require("fs"); - Вызовы к
define(...) - Документацию, описывающую, как
requireили импортировать библиотеку
Примеры глобальных библиотек
Поскольку обычно легко превратить глобальную библиотеку в UMD-библиотеку, очень немногие популярные библиотеки до сих пор написаны в стиле глобальных библиотек. Однако небольшие библиотеки, требующие DOM (или не имеющие зависимостей), могут быть глобальными.
Шаблон глобальной библиотеки
Файл шаблона global.d.ts определяет пример библиотеки myLib. Обязательно прочтите примечание “Предотвращение конфликтов имен”.
UMD
UMD-модуль — это модуль, который можно либо использовать как модуль (через импорт), либо как глобальный (при выполнении в среде без загрузчика модулей). Многие популярные библиотеки, такие как Moment.js, написаны таким образом. Например, в Node.js или с использованием RequireJS вы бы написали:
import moment = require("moment");
console.log(moment.format()); в то время как в обычной среде браузера вы бы написали:
console.log(moment.format());
Определение UMD-библиотеки
UMD-модули проверяют наличие среды загрузчика модулей. Это легко распознаваемый шаблон, который выглядит примерно так:
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(["libName"], factory);
} else if (typeof module === "object" && module.exports) {
module.exports = factory(require("libName"));
} else {
root.returnExports = factory(root.libName);
}
}(this, function (b) { Если вы видите тесты на typeof define, typeof window, или typeof module в коде библиотеки, особенно в начале файла, это, практически всегда, UMD-библиотека.
Документация для UMD-библиотек также часто демонстрирует пример «Использование в Node.js», показывающий require, и пример «Использование в браузере», показывающий использование тега <script> для загрузки скрипта.
Примеры UMD-библиотек
Большинство популярных библиотек теперь доступны как UMD-пакеты. Примеры включают jQuery, Moment.js, lodash и многие другие.
Шаблон
Используйте шаблон module-plugin.d.ts.
Использование зависимостей
Существует несколько типов зависимостей, которые может иметь ваша библиотека. В этом разделе показано, как импортировать их в файл объявления.
Зависимости от глобальных библиотек
Если ваша библиотека зависит от глобальной библиотеки, используйте директиву /// <reference types="..." />.
/// <reference types="someLib" /> function getThing(): someLib.thing;
Зависимости от модулей
Если ваша библиотека зависит от модуля, используйте оператор import.
import * as moment from "moment"; function getThing(): moment;
Зависимости от UMD-библиотек
От глобальной библиотеки
Если ваша глобальная библиотека зависит от UMD-модуля, используйте директиву /// <reference types.
/// <reference types="moment" /> function getThing(): moment;
От модуля или UMD-библиотеки
Если ваш модуль или UMD-библиотека зависит от UMD-библиотеки, используйте оператор import.
import * as someLib from "someLib";
Не используйте директиву /// <reference для объявления зависимости от UMD-библиотеки!
Примечания
Предотвращение конфликтов имен
Обратите внимание, что при написании файла объявления глобальной библиотеки можно определить множество типов в глобальной области видимости. Мы настоятельно рекомендуем этого не делать, поскольку это может привести к неразрешимым конфликтам имен при наличии нескольких файлов объявления в проекте.
Простое правило — объявлять типы только в именованных пространствах, определенных глобальной переменной библиотеки. Например, если библиотека определяет глобальную переменную ‘cats’, вы должны написать
declare namespace cats {
interface KittySettings {}
} Но не
// at top-level
interface CatsKittySettings {} Это руководство также гарантирует, что библиотеку можно перевести в UMD-формат без нарушения работы пользователей, использующих файл объявления.
Влияние ES6 на сигнатуры вызовов модулей
Многие популярные библиотеки, такие как Express, представляют собой вызываемую функцию при импорте. Например, типичное использование Express выглядит так:
import exp = require("express");
var app = exp(); В совместимых с ES6 загрузчиках модулей, верхнеуровневый объект (здесь импортированный как exp) может иметь только свойства; верхнеуровневый объект модуля никогда не может быть вызываемым.
Наиболее распространенное решение в этом случае — определить экспорт default для вызываемого/создаваемого объекта; загрузчики модулей обычно автоматически обнаруживают эту ситуацию и заменяют верхнеуровневый объект экспортом default. TypeScript может справиться с этим за вас, если у вас есть "esModuleInterop": true в вашем tsconfig.json.
© 2012-2023 Microsoft
Licensed under the Apache License, Version 2.0.
https://www.typescriptlang.org/docs/handbook/declaration-files/library-structures.html