Spec-Zone.ru › TypeScript 5.1

Модули .d.ts

Сравнение JavaScript с примером DTS

Общие паттерны CommonJS

Модуль, использующий паттерны CommonJS, использует module.exports для описания экспортируемых значений. Например, вот модуль, который экспортирует функцию и числовую константу:

const maxInterval = 12;

function getArrayLength(arr) {
  return arr.length;
}

module.exports = {
  getArrayLength,
  maxInterval,
};

Это можно описать следующим .d.ts:

export function getArrayLength(arr: any[]): number;
export const maxInterval: 12;

Игровой плацдарм TypeScript может показать вам .d.ts эквивалент для кода JavaScript. Вы можете попробовать самостоятельно здесь.

Синтаксис .d.ts намеренно похож на синтаксис модулей ES. Модули ES были ратифицированы TC39 в 2015 году как часть ES2015 (ES6), хотя они были доступны через транспайлеры уже давно. Однако, если у вас есть база кода JavaScript, использующая модули ES:

export function getArrayLength(arr) {
  return arr.length;
}

Это имело бы следующий .d.ts эквивалент:

export function getArrayLength(arr: any[]): number;

Экспорт по умолчанию

В CommonJS вы можете экспортировать любое значение как экспорт по умолчанию, например, здесь модуль регулярных выражений:

module.exports = /hello( world)?/;

Что можно описать следующим .d.ts:

declare const helloWorld: RegExp;
export default helloWorld;

Или число:

module.exports = 3.142;
declare const pi: number;
export default pi;

Один из стилей экспорта в CommonJS — экспорт функции. Поскольку функция также является объектом, можно добавлять дополнительные поля, и они включаются в экспорт.

function getArrayLength(arr) {
  return arr.length;
}
getArrayLength.maxInterval = 12;

module.exports = getArrayLength;

Что можно описать следующим образом:

export default function getArrayLength(arr: any[]): number;
export const maxInterval: 12;

Обратите внимание, что использование export default в ваших файлах .d.ts требует esModuleInterop: true, чтобы это работало. Если вы не можете использовать esModuleInterop: true в вашем проекте, например, когда вы отправляете PR в Definitely Typed, вам придется использовать синтаксис export= вместо этого. Этот более старый синтаксис сложнее в использовании, но работает везде. Вот как должен быть написан приведенный выше пример, используя export=:

declare function getArrayLength(arr: any[]): number;
declare namespace getArrayLength {
  declare const maxInterval: 12;
}

export = getArrayLength;

См. Модуль: Функции для получения подробной информации о работе этого и страницу справки по модулям.

Обработка множественных импортов

Существует множество способов импортировать модуль в современном потребительском коде:

const fastify = require("fastify");
const { fastify } = require("fastify");
import fastify = require("fastify");
import * as Fastify from "fastify";
import { fastify, FastifyInstance } from "fastify";
import fastify from "fastify";
import fastify, { FastifyInstance } from "fastify";

Для поддержки всех этих случаев код JavaScript должен фактически поддерживать все эти паттерны. Чтобы поддержать многие из этих паттернов, модуль CommonJS должен выглядеть примерно так:

class FastifyInstance {}

function fastify() {
  return new FastifyInstance();
}

fastify.FastifyInstance = FastifyInstance;

// Allows for { fastify }
fastify.fastify = fastify;
// Allows for strict ES Module support
fastify.default = fastify;
// Sets the default export
module.exports = fastify;

Типы в модулях

Вы можете захотеть предоставить тип для кода JavaScript, которого не существует

function getArrayMetadata(arr) {
  return {
    length: getArrayLength(arr),
    firstObject: arr[0],
  };
}

module.exports = {
  getArrayMetadata,
};

Это можно описать следующим образом:

export type ArrayMetadata = {
  length: number;
  firstObject: any | undefined;
};
export function getArrayMetadata(arr: any[]): ArrayMetadata;

Этот пример является хорошим случаем для использования универсальных типов, чтобы предоставить более подробную информацию о типах:

export type ArrayMetadata<ArrType> = {
  length: number;
  firstObject: ArrType | undefined;
};

export function getArrayMetadata<ArrType>(
  arr: ArrType[]
): ArrayMetadata<ArrType>;

Теперь тип массива распространяется на тип ArrayMetadata.

Экспортируемые типы могут затем повторно использоваться потребителями модулей с помощью import или import type в коде TypeScript или импорта JSDoc.

Пространства имен в коде модуля

Попытка описать временные отношения кода JavaScript может быть сложной. Когда синтаксис, похожий на модули ES, не предоставляет достаточно инструментов для описания экспортов, можно использовать namespaces.

Например, у вас могут быть достаточно сложные типы, чтобы вы решили сгруппировать их в пространстве имен внутри вашего .d.ts:

// This represents the JavaScript class which would be available at runtime
export class API {
  constructor(baseURL: string);
  getInfo(opts: API.InfoRequest): API.InfoResponse;
}

// This namespace is merged with the API class and allows for consumers, and this file
// to have types which are nested away in their own sections.
declare namespace API {
  export interface InfoRequest {
    id: string;
  }

  export interface InfoResponse {
    width: number;
    height: number;
  }
}

Чтобы понять, как работают пространства имен в файлах .d.ts прочитайте .d.ts подробный обзор.

Необязательное глобальное использование

Вы можете использовать export as namespace для объявления того, что ваш модуль будет доступен в глобальном пространстве имен в контекстах UMD:

export as namespace moduleName;

Пример справки

Чтобы дать вам представление о том, как все эти части могут объединиться, вот пример .d.ts с которого можно начать при создании нового модуля

// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~]
// Project: [~THE PROJECT NAME~]
// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]>

/*~ This is the module template file. You should rename it to index.d.ts
 *~ and place it in a folder with the same name as the module.
 *~ For example, if you were writing a file for "super-greeter", this
 *~ file should be 'super-greeter/index.d.ts'
 */

/*~ If this module is a UMD module that exposes a global variable 'myLib' when
 *~ loaded outside a module loader environment, declare that global here.
 *~ Otherwise, delete this declaration.
 */
export as namespace myLib;

/*~ If this module exports functions, declare them like so.
 */
export function myFunction(a: string): string;
export function myOtherFunction(a: number): number;

/*~ You can declare types that are available via importing the module */
export interface SomeType {
  name: string;
  length: number;
  extras?: string[];
}

/*~ You can declare properties of the module using const, let, or var */
export const myField: number;

Структура файлов библиотеки

Структура ваших файлов объявлений должна отражать структуру библиотеки.

Библиотека может состоять из нескольких модулей, например

myLib
  +---- index.js
  +---- foo.js
  +---- bar
         +---- index.js
         +---- baz.js

Их можно импортировать как

var a = require("myLib");
var b = require("myLib/foo");
var c = require("myLib/bar");
var d = require("myLib/bar/baz");

Таким образом, ваши файлы объявлений должны быть

@types/myLib
  +---- index.d.ts
  +---- foo.d.ts
  +---- bar
         +---- index.d.ts
         +---- baz.d.ts

Тестирование ваших типов

Если вы планируете отправить эти изменения в DefinitelyTyped для использования всеми, мы рекомендуем:

  1. Создать новую папку в node_modules/@types/[libname]
  2. Создать index.d.ts в этой папке и скопировать пример в неё
  3. Выяснить, где ваш код использования модуля прерывается, и начать заполнять index.d.ts
  4. После завершения работы скопируйте DefinitelyTyped/DefinitelyTyped и следуйте инструкциям в файле README.

В противном случае

  1. Создайте новый файл в корне вашего исходного дерева: [libname].d.ts
  2. Добавьте declare module "[libname]" { }
  3. Добавьте шаблон внутрь фигурных скобок declare module и выясните, где прерывается использование

© 2012-2023 Microsoft
Licensed under the Apache License, Version 2.0.
https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API