如何创建自己的 TypeScript 类型定义文件 (.d.ts)?
TypeScript 是 JavaScript 的一个超集,它提供静态类型功能,可以提升代码质量并在编译期间捕获错误。为了充分利用 TypeScript 的静态类型功能,项目中使用的外部 JavaScript 库和模块必须拥有类型定义文件 (.d.ts)。这些类型定义文件描述了外部实体公开的类型和接口,使 TypeScript 编译器能够理解它们的形状和行为。
在本文中,我们将逐步探索创建自定义 TypeScript 类型定义文件的过程,使开发者能够在项目中受益于静态类型。
先决条件
类型定义文件 (.d.ts) 充当 JavaScript 代码和 TypeScript 编译器之间的接口。它们描述了 JavaScript 库或框架中存在的类型、函数、类和模块。这些文件使 TypeScript 编译器能够执行类型检查,并在 IDE 中提供丰富的 IntelliSense 支持。
在深入创建类型定义文件之前,请确保您已设置以下先决条件 -
对 TypeScript 有基本的了解。
TypeScript 已全局安装在您的系统中。您可以使用以下命令通过 npm 安装它 -
npm install -g typescript
步骤 1:确定库结构
要创建类型定义文件,您需要了解要为其创建类型的库或模块的结构。这涉及分析 JavaScript 代码,理解公开的函数、类、对象及其对应的类型。
步骤 2:从空的 .d.ts 文件开始
创建一个空的 .d.ts 文件,其名称应与您要为其创建类型的 JavaScript 库或模块相同。例如,如果您的库名为 "my-library", 则类型定义文件应命名为 "my-library.d.ts"。
步骤 3:声明模块
创建类型定义文件的第一步是使用 declare module 语法声明模块。这会告诉 TypeScript 您正在为特定模块或库定义类型。以下是示例 -
declare module 'my-library' {
// 类型定义放在此处
}
步骤 4:定义类型和接口
在模块声明中,您可以定义描述库结构的类型和接口。您可以声明对象的接口、函数的类型等等。
让我们考虑一个例子,我们有一个名为 "math-library" 的库,其中包含一个函数 add,该函数接受两个数字作为参数并返回它们的和 -
declare module 'math-library' {
export function add(a: number, b: number): number;
}
在上面的例子中,我们声明了一个名为"math-library"的模块,并导出了一个函数 add,该函数接受两个数字(a 和 b)作为参数并返回一个数字。
步骤 5:导出类型和接口
为了使定义的类型和接口可供其他 TypeScript 文件使用,您需要显式导出它们。在每个类型或接口声明前使用 export 关键字。以下是扩展我们之前的 math-library 示例的示例 -
declare module 'math-library' {
export function add(a: number, b: number): number;
export interface Calculator {
name: string;
add(a: number, b: number): number;
}
}
在更新的示例中,我们导出一个名为 Calculator 的新接口,该接口具有 name 属性,以及一个方法 add,其签名与我们之前定义的 add 函数相同。
步骤 6:使用环境声明
环境声明允许您为没有 TypeScript 特定注解的现有 JavaScript 代码描述类型。它们包含在 declare global 块中。以下是示例 -
declare global {
interface Array<T> {
filter(callbackfn: (value: T, index: number, array: T[]) => boolean): T[];
}
}
在上面的示例中,我们声明了一个全局接口 Array<T> 来扩展内置的 Array 类型。我们添加了一个新的方法过滤器,并使用一个回调函数指定其签名,该回调函数接受值、索引和数组本身作为参数。
步骤 7:引用外部类型定义(可选)
如果您的类型定义文件依赖于其他外部类型定义文件,您可以使用 /// <reference types="..."/> 语法引用它们。例如,如果您的库依赖于流行库"lodash"的类型定义,您可以按如下方式添加引用 -
/// <reference types="lodash" />
这可确保 TypeScript 编译器在编译代码时包含来自"lodash"的类型定义。
步骤 8:测试和优化
定义类型定义文件后,务必使用代码库对其进行测试。在 TypeScript 项目中导入或引用该库,并使用定义的类型和接口。如果 TypeScript 编译器抛出任何错误,或者库的行为与定义的类型不匹配,请返回类型定义文件并进行相应的优化。
示例 1
我们来看一个实际的例子。
创建一个名为 my-library 的模块,其中包含一个实用函数 capitalize,该函数接受一个字符串并返回其大写版本。
my-library.js
function capitalize(st) {
return st.charAt(0).toUpperCase() + st.slice(1);
}
module.exports = {
capitalize: capitalize,
};
现在,我们将创建一个类型定义文件,通过编译时类型检查来限制导出的 capitalize 函数的使用 -
首先,创建一个名为 my-library.d.ts 的新文件,其中包含以下内容 -
declare module 'my-library' {
export function capitalize(str: string): string;
}
在上面的示例中,我们声明了一个名为"my-library"的模块,并导出了一个函数 capitalize,该函数接受一个字符串参数并返回一个字符串。
现在,您可以在 TypeScript 代码中使用 capitalize 函数,并确保类型安全。我们现在创建一个 app.ts 文件来使用我们的 capitalize 函数 -
app.ts
/// <reference types="node" />
const { capitalize } = require("./my-library");
const result = capitalize("hello");
console.log(result); // 输出:Hello
通过添加 /// <reference types="node" /> 指令,您可以告知 TypeScript 使用已安装的 Node.js 类型定义来执行 require 函数。现在,TypeScript 应该可以识别 require 函数了。
通过提供准确的类型定义,TypeScript 编译器可以验证 capitalize 函数的用法,从而避免任何潜在的类型错误。
输出
它将产生以下输出 -
Hello
结论
创建 TypeScript 类型定义文件 (.d.ts) 可以让开发者利用静态类型的强大功能,并在使用外部 JavaScript 库和模块时提升开发者体验。通过遵循逐步分析库结构、声明模块、定义类型和接口以及测试和优化类型定义的流程,开发人员可以确保项目的类型定义准确且全面。有了类型定义文件,TypeScript 可以提高代码质量、实现早期错误检测并增强可维护性。通过投入时间创建精确的类型定义,开发人员可以在开发工作流程中充分利用 TypeScript 的优势。


