Typescript学习教程,从入门到精通,TypeScript 类型声明文件详解(15)
TypeScript 类型声明文件详解
TypeScript 的类型声明文件(通常以 .d.ts
结尾)是用于描述 JavaScript 代码的类型信息的文件。它们使得 TypeScript 能够理解 JavaScript 库的结构,从而提供类型检查和智能提示。
1. 获取类型声明文件
1.1 内置 API 的类型声明文件
TypeScript 提供了内置 JavaScript API 的类型声明文件,这些文件通常位于 TypeScript 的类型声明库中。例如,lib.d.ts
包含了 JavaScript 核心库的类型声明。
1.2 常用第三方 JavaScript 库的类型声明文件
对于第三方库,类型声明文件通常由社区维护,并发布在 DefinitelyTyped 仓库中。大多数流行的库都可以通过 npm 安装对应的类型声明包,命名格式为 @types/库名
。
示例:安装 lodash
的类型声明
npm install --save-dev @types/lodash
2. 定义类型声明文件
2.1 基本语法
类型声明文件使用 .d.ts
扩展名,主要包含类型定义、接口声明、模块导出等。
示例:my-lib.d.ts
// 声明一个全局变量
declare var myLib: MyLibType;// 声明一个全局函数
declare function myFunction(param: string): number;// 声明一个接口
interface MyLibType {name: string;version: number;doSomething: () => void;
}// 声明一个模块
declare module "my-module" {export function foo(): string;export const bar: number;
}
2.2 模块声明
对于使用模块化的库,可以使用 declare module
来声明模块的导出内容。
示例:声明一个模块
declare module "express" {import * as express from "express";export = express;
}
2.3 命名空间声明
使用 declare namespace
来声明全局命名空间中的对象。
示例:声明一个命名空间
declare namespace MyNamespace {function greet(name: string): void;let version: number;
}
3. 为 .js
文件编写类型声明文件
虽然 TypeScript 支持直接导入 .js
文件,但为了获得更好的类型检查和智能提示,建议为 .js
文件编写对应的 .d.ts
文件。
3.1 基本步骤
- 创建
.d.ts
文件:与对应的.js
文件同名,但扩展名为.d.ts
。 - 声明模块:使用
declare module
或export
语法。 - 定义类型:根据
.js
文件的导出内容定义相应的类型。
示例:假设有一个 math.js
文件
// math.js
function add(a, b) {return a + b;
}function subtract(a, b) {return a - b;
}module.exports = { add, subtract };
对应的 math.d.ts
文件
// math.d.ts
export function add(a: number, b: number): number;
export function subtract(a: number, b: number): number;
3.2 使用 declare
关键字
对于全局变量或函数,可以使用 declare
来声明。
示例:声明全局函数
// globals.d.ts
declare function parseJSON(jsonString: string): any;
4. 实战案例
4.1 为自定义模块编写类型声明
假设有一个 utils.js
文件:
// utils.js
function capitalize(str) {return str.charAt(0).toUpperCase() + str.slice(1);
}function isString(value) {return typeof value === 'string';
}module.exports = { capitalize, isString };
对应的 utils.d.ts
文件
// utils.d.ts
export function capitalize(str: string): string;
export function isString(value: any): boolean;
使用示例
// app.ts
import { capitalize, isString } from "./utils";const name = "world";
const capitalized = capitalize(name); // "World"
const isNameString = isString(name); // true
4.2 为第三方库编写自定义类型声明
假设有一个 custom-lib.js
文件:
// custom-lib.js
function greet(name) {console.log(`Hello, ${name}!`);
}const version = "1.0.0";module.exports = { greet, version };
对应的 custom-lib.d.ts
文件
// custom-lib.d.ts
export function greet(name: string): void;
export const version: string;
使用示例
// app.ts
import { greet, version } from "custom-lib";greet("Alice"); // 输出: Hello, Alice!
console.log(version); // "1.0.0"
4.3 使用 declare
声明全局库
假设有一个全局库 global-lib.js
:
// global-lib.js
function setup() {console.log("Library initialized");
}window.globalLib = { setup };
对应的 global-lib.d.ts
文件
// global-lib.d.ts
declare function setup(): void;
declare namespace globalLib {function setup(): void;
}
使用示例
// app.ts
setup(); // 调用全局函数
globalLib.setup(); // 调用命名空间中的函数
5. 高级主题
5.1 泛型
类型声明文件中可以使用泛型来定义可复用的类型。
示例:泛型函数
// generics.d.ts
export function identity<T>(arg: T): T;
5.2 联合类型和交叉类型
可以声明联合类型和交叉类型以增强类型表达能力。
示例:联合类型
// union.d.ts
export type StringOrNumber = string | number;
示例:交叉类型
// intersection.d.ts
export type Person = { name: string } & { age: number };
5.3 命名空间与模块
在现代 TypeScript 中,推荐使用 ES6 模块语法,但在某些情况下,命名空间仍然有其用途。
示例:使用命名空间
// namespace.d.ts
declare namespace MyLibrary {function init(): void;namespace Utils {function helper(): void;}
}
使用示例
// app.ts
MyLibrary.init();
MyLibrary.Utils.helper();
6. 总结
TypeScript 的类型声明文件是实现类型安全和智能提示的关键。通过正确地编写和使用类型声明文件,可以大幅提升开发效率和代码质量。以下是一些关键点:
- 模块化声明:使用
export
和import
语法进行模块化声明。 - 命名空间:在需要时使用
declare namespace
声明全局对象。 - 类型定义:详细定义函数、接口、类等类型的结构和行为。
- 第三方库:利用 DefinitelyTyped 提供的类型声明包,或根据需要编写自定义声明。