模組 .d.ts

比較 JavaScript 與 .d.ts 示例

常見的 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 演練場(Playground)可以向您展示 JavaScript 程式碼對應的 .d.ts。您可以 點選此處親自嘗試

.d.ts 語法特意看起來像 ES 模組語法。ES 模組於 2015 年作為 ES2015 (ES6) 的一部分由 TC39 批准,雖然它透過轉譯器已經存在很長時間了,但如果您有一個使用 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 = helloWorld;

或者一個數字

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

CommonJS 中匯出的一種風格是匯出函式。因為函式也是物件,所以可以新增額外的欄位並將其包含在匯出中。

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

這可以透過以下方式描述

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

詳情請參閱 模組:函式 以及 模組參考 頁面。

處理多種匯入方式

在現代消費程式碼中,匯入模組的方式有很多種

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 type,或者使用 JSDoc 匯入

模組程式碼中的名稱空間

嘗試描述 JavaScript 程式碼的執行時關係可能很棘手。當類似 ES 模組的語法不足以描述匯出時,您可以使用 namespaces

例如,您可能擁有足夠複雜的型別來描述,因此選擇將它們放在 .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 並按照 README 中的說明進行操作。

否則

  1. 在您的原始碼樹根目錄下建立一個新檔案:[libname].d.ts
  2. 新增 declare module "[libname]" { }
  3. 將模板新增到 declare module 的大括號內,並檢視您的使用在何處報錯

TypeScript 文件是一個開源專案。透過 傳送 Pull Request 來幫助我們改進這些頁面 ❤

此頁面的貢獻者
MHMohamed Hegazy (53)
OTOrta Therox (15)
DSDavid Sherret (1)
MFMike Frysinger (1)
Hhzrong (1)
5+

最後更新:2026 年 3 月 27 日