模組 .d.ts

比較 JavaScript 與範例 DTS

常見 CommonJS 模式

使用 CommonJS 模式的模組使用 module.exports 來描述所匯出的值。例如,以下是匯出函式和數字常數的模組

js
const maxInterval = 12;
function getArrayLength(arr) {
return arr.length;
}
module.exports = {
getArrayLength,
maxInterval,
};

這可以用以下 .d.ts 來描述

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

TypeScript 遊樂場可以顯示 JavaScript 程式碼的 .d.ts 等效版本。你可以在此親自嘗試

.d.ts 語法故意看起來像ES 模組語法。ES 模組在 2015 年由 TC39 批准為 ES2015 (ES6) 的一部分,雖然它已經透過轉譯器提供很長一段時間了,但是如果你有使用 ES 模組的 JavaScript 程式碼庫

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

這將具有下列等效的 .d.ts

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

預設匯出

在 CommonJS 中,您可以將任何值匯出為預設匯出,例如這裡是一個正規表示式模組

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

可以用下列 .d.ts 來描述

ts
declare const helloWorld: RegExp;
export default helloWorld;

或一個數字

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

CommonJS 中的一種匯出樣式是匯出一個函式。由於函式也是一個物件,因此可以新增額外欄位,並包含在匯出中。

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

可以用下列來描述

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

請注意,在 .d.ts 檔案中使用 export default 需要 esModuleInterop: true 才能運作。如果您無法在專案中使用 esModuleInterop: true,例如當您提交 PR 到 Definitely Typed 時,您必須改用 export= 語法。這個較舊的語法較難使用,但可以在所有地方運作。以下是使用 export= 編寫上述範例的方式

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

請參閱 模組:函式,以了解其運作方式的詳細資訊,以及 模組參考 頁面。

處理大量使用 import

在現代使用代碼中,有許多方法可以匯入模組

ts
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 模組需要看起來像

js
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 代碼類型

js
function getArrayMetadata(arr) {
return {
length: getArrayLength(arr),
firstObject: arr[0],
};
}
module.exports = {
getArrayMetadata,
};

這可以用以下方式描述

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

此範例是 使用泛型 提供更豐富類型資訊的良好案例

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

現在陣列的類型會傳播到 ArrayMetadata 類型。

然後,匯出的類型可以透過使用 TypeScript 代碼中的 importimport typeJSDoc 匯入 來重複使用模組的使用者。

模組代碼中的命名空間

嘗試說明 JavaScript 程式碼的執行時間關係可能會很棘手。當類似 ES 模組的語法無法提供足夠的工具來描述匯出時,您可以使用命名空間

例如,您可能有足夠複雜的類型來描述,您選擇在.d.ts中對它們命名。

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 背景中會在全域範圍內提供。

ts
export as namespace moduleName;

參考範例

為了讓您了解所有這些部分如何結合在一起,以下是製作新模組時可以參考的 .d.ts

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

可以匯入為

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 並遵循自述檔案中的說明。

否則

  1. 在來源樹的根目錄中建立一個新檔案:[libname].d.ts
  2. 新增 declare module "[libname]" { }
  3. 在宣告模組的大括號內新增範本,並查看使用中發生中斷的地方

TypeScript 文件是一個開放原始碼專案。協助我們改善這些頁面 透過傳送 Pull Request

此頁面的貢獻者
MHMohamed Hegazy (53)
OTOrta Therox (15)
MFMike Frysinger (1)
Hhzrong (1)
GSGuilherme Samuel (1)
4+

最後更新:2024 年 3 月 21 日