跳至内容
张叶安的小站
用户工具
登录
站点工具
搜索
工具
显示页面
过去修订
反向链接
最近更改
媒体管理器
网站地图
登录
>
最近更改
媒体管理器
网站地图
您的足迹:
typescript:第十一章类型声明文件
本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。
====== 第十一章 类型声明文件 ====== 类型声明文件(.d.ts)是TypeScript项目的重要组成部分,它描述了JavaScript库的类型信息,使TypeScript能够在使用JavaScript库时提供类型检查和智能提示。 ===== 11.1 声明文件基础 ===== ==== 11.1.1 声明文件的作用 ==== 类型声明文件只包含类型信息,不包含实现: - 描述现有JavaScript代码的类型 - 为第三方库提供类型定义 - 扩展全局对象的类型 <code typescript> // mylib.d.ts - 声明文件示例 declare module "mylib" { export interface User { id: number; name: string; } export function createUser(name: string): User; export const version: string; } </code> ==== 11.1.2 声明文件位置 ==== TypeScript按以下顺序查找声明文件: 1. **内置类型**:lib.d.ts等 2. **package.json中的types字段**:指定入口声明文件 3. **@types包**:DefinitelyTyped社区维护的类型 4. **项目中声明文件**: - tsconfig.json中files/include指定的文件 - 与.js文件同名的.d.ts文件 - 项目根目录的.d.ts文件 ===== 11.2 创建声明文件 ===== ==== 11.2.1 声明语句类型 ==== <code typescript> // types.d.ts // 声明变量 declare const VERSION: string; declare let config: { apiUrl: string }; // 声明函数 declare function greet(name: string): string; declare function process(callback: (result: string) => void): void; // 声明类 declare class Animal { constructor(name: string); name: string; move(distance: number): void; } // 声明枚举 declare enum Direction { Up, Down, Left, Right } // 声明模块 export interface Config { debug: boolean; } // 声明命名空间 declare namespace MyLib { function doSomething(): void; const version: string; } </code> ==== 11.2.2 为JavaScript库编写声明 ==== 假设有一个JavaScript库my-utils.js: <code javascript> // my-utils.js function add(a, b) { return a + b; } class Calculator { constructor() { this.result = 0; } multiply(x) { return this.result *= x; } } module.exports = { add, Calculator }; </code> 对应的声明文件: <code typescript> // my-utils.d.ts export function add(a: number, b: number): number; export class Calculator { result: number; constructor(); multiply(x: number): number; } </code> ==== 11.2.3 UMD模块声明 ==== <code typescript> // 支持CommonJS/AMD/全局变量 declare namespace MyLibrary { function doSomething(): void; const version: string; } export = MyLibrary; export as namespace MyLibrary; </code> ===== 11.3 模块声明模式 ===== ==== 11.3.1 全局库声明 ==== 用于直接通过script标签引入的库: <code typescript> // jquery.d.ts declare const $: JQueryStatic; declare const jQuery: JQueryStatic; interface JQueryStatic { (selector: string): JQuery; ajax(url: string, settings?: JQuery.AjaxSettings): JQuery.jqXHR; fn: any; extend(deep: boolean, target: any, ...objects: any[]): any; } interface JQuery { addClass(className: string): this; attr(attributeName: string): string | undefined; attr(attributeName: string, value: string | number): this; on(events: string, handler: (event: JQuery.Event) => void): this; off(events: string, handler?: (event: JQuery.Event) => void): this; } declare namespace JQuery { interface AjaxSettings { url?: string; method?: string; data?: any; success?: (data: any, textStatus: string, jqXHR: jqXHR) => void; } interface Event { type: string; target: Element; preventDefault(): void; stopPropagation(): void; } interface jqXHR { done(callback: (data: any, textStatus: string, jqXHR: jqXHR) => void): this; fail(callback: (jqXHR: jqXHR, textStatus: string, errorThrown: string) => void): this; } } </code> ==== 11.3.2 模块库声明 ==== <code typescript> // lodash.d.ts declare module "lodash" { export function chunk<T>(array: T[], size: number): T[][]; export function debounce<T extends (...args: any[]) => any>( func: T, wait?: number, options?: DebounceSettings ): T & { cancel(): void; flush(): ReturnType<T> }; export function throttle<T extends (...args: any[]) => any>( func: T, wait?: number, options?: ThrottleSettings ): T & { cancel(): void; flush(): ReturnType<T> }; export function cloneDeep<T>(value: T): T; export function merge<TObject, TSource>( object: TObject, source: TSource ): TObject & TSource; export function groupBy<T>( collection: T[], iteratee: ((value: T) => string) | string ): { [key: string]: T[] }; interface DebounceSettings { leading?: boolean; trailing?: boolean; maxWait?: number; } interface ThrottleSettings { leading?: boolean; trailing?: boolean; } } </code> ==== 11.3.3 插件扩展声明 ==== 为现有库添加方法: <code typescript> // jquery-myplugin.d.ts /// <reference types="jquery" /> declare global { interface JQuery { myPlugin(options?: MyPluginOptions): this; greenify(): this; } interface JQueryStatic { myPlugin: { defaults: MyPluginOptions; setDefaults(options: MyPluginOptions): void; }; } } interface MyPluginOptions { color?: string; backgroundColor?: string; } export {}; </code> ===== 11.4 高级声明技术 ===== ==== 11.4.1 条件类型与推断 ==== <code typescript> // 声明条件类型 type ElementType<T> = T extends (infer E)[] ? E : T; // 声明映射类型 type Readonly<T> = { readonly [P in keyof T]: T[P]; }; type Partial<T> = { [P in keyof T]?: T[P]; }; type Required<T> = { [P in keyof T]-?: T[P]; }; type Pick<T, K extends keyof T> = { [P in K]: T[P]; }; type Record<K extends keyof any, T> = { [P in K]: T; }; </code> ==== 11.4.2 函数重载声明 ==== <code typescript> // 复杂函数重载 declare function fetch(url: string): Promise<Response>; declare function fetch( url: string, options: RequestInit ): Promise<Response>; declare function fetch( input: RequestInfo, init?: RequestInit ): Promise<Response>; // 基于返回类型的重载 declare function createElement(tagName: "a"): HTMLAnchorElement; declare function createElement(tagName: "canvas"): HTMLCanvasElement; declare function createElement(tagName: "div"): HTMLDivElement; declare function createElement(tagName: "input"): HTMLInputElement; declare function createElement(tagName: "span"): HTMLSpanElement; declare function createElement(tagName: string): HTMLElement; </code> ==== 11.4.3 泛型约束声明 ==== <code typescript> // 泛型接口 declare interface ApiResponse<T = any> { data: T; status: number; message: string; } declare interface PaginatedResponse<T> { items: T[]; total: number; page: number; pageSize: number; } // 泛型函数约束 declare function find<T, K extends keyof T>( array: T[], key: K, value: T[K] ): T | undefined; declare function sortBy<T, K extends keyof T>( array: T[], key: K ): T[]; declare function groupBy<T, K extends keyof T>( array: T[], key: K ): Map<T[K], T[]>; </code> ===== 11.5 发布类型定义 ===== ==== 11.5.1 与npm包一起发布 ==== 在package.json中指定types字段: <code json> { "name": "my-library", "version": "1.0.0", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { ".": { "import": "./dist/index.mjs", "require": "./dist/index.js", "types": "./dist/index.d.ts" }, "./package.json": "./package.json" }, "files": [ "dist", "src" ] } </code> ==== 11.5.2 提交到DefinitelyTyped ==== 对于没有内置类型的流行库,可以提交到@types组织: 1. Fork DefinitelyTyped/DefinitelyTyped 2. 在types目录创建包文件夹 3. 编写index.d.ts和测试文件 4. 提交Pull Request 结构: <code> types/my-library/ ├── index.d.ts # 主声明文件 ├── my-library-tests.ts # 测试文件 ├── tsconfig.json # 配置 └── package.json # {"private": true} </code> ===== 11.6 声明文件最佳实践 ===== ==== 11.6.1 避免常见错误 ==== <code typescript> // ❌ 错误:在声明文件中使用实现 export function add(a: number, b: number) { return a + b; } // ✅ 正确:只声明类型 export function add(a: number, b: number): number; // ❌ 错误:导入使用require import fs = require("fs"); // ✅ 正确:使用ES模块语法 import * as fs from "fs"; import type { Readable } from "stream"; // ❌ 错误:使用any export function process(data: any): any; // ✅ 正确:使用unknown或具体类型 export function process<T>(data: T): Processed<T>; </code> ==== 11.6.2 文档与注释 ==== <code typescript> /** * 用户管理类 * @example * ```ts * const userManager = new UserManager(); * const user = await userManager.create({ name: "John" }); * ``` */ export class UserManager { /** * 创建新用户 * @param data - 用户数据 * @returns 创建的用户对象 * @throws {ValidationError} 数据验证失败时抛出 */ create(data: CreateUserData): Promise<User>; /** * 根据ID查找用户 * @param id - 用户ID * @returns 用户对象,不存在时返回null */ findById(id: string): Promise<User | null>; } /** 创建用户的数据 */ export interface CreateUserData { /** 用户名,3-20个字符 */ name: string; /** 邮箱地址 */ email: string; /** 可选的个人简介 */ bio?: string; } </code> ==== 11.6.3 版本兼容性 ==== <code typescript> // 使用ts版本标记 // TypeScript Version: 4.0 // 条件类型特性 // TypeScript Version: 2.8 // 模板字面量类型 // TypeScript Version: 4.1 // 在package.json中指定 { "name": "@types/mylib", "version": "1.0.0", "typescript": { "version": ">=4.0.0" } } </code> ===== 11.7 实际案例 ===== ==== 11.7.1 Express类型定义 ==== <code typescript> // express 类型定义简化版 declare namespace Express { interface Request { body: any; params: { [key: string]: string }; query: { [key: string]: string | string[] }; headers: IncomingHttpHeaders; ip?: string; path: string; protocol: string; secure: boolean; xhr: boolean; } interface Response { status(code: number): this; json(body?: any): this; send(body?: any): this; redirect(url: string): this; render(view: string, options?: object): void; } interface NextFunction { (err?: any): void; } interface Application { use(...handlers: RequestHandler[]): this; get(path: string, ...handlers: RequestHandler[]): this; post(path: string, ...handlers: RequestHandler[]): this; listen(port: number, callback?: () => void): Server; } } type RequestHandler = ( req: Express.Request, res: Express.Response, next: Express.NextFunction ) => void | Promise<void>; declare function express(): Express.Application; declare namespace express { export function json(): RequestHandler; export function urlencoded(options?: { extended?: boolean }): RequestHandler; export function static(root: string, options?: any): RequestHandler; } export = express; </code> ==== 11.7.2 数据库驱动类型 ==== <code typescript> // 通用数据库驱动类型 export interface DatabaseConnection { query<T = any>(sql: string, params?: any[]): Promise<T[]>; execute(sql: string, params?: any[]): Promise<{ affectedRows: number }>; transaction<T>(callback: (trx: Transaction) => Promise<T>): Promise<T>; close(): Promise<void>; } export interface Transaction extends DatabaseConnection { rollback(): Promise<void>; commit(): Promise<void>; } export interface QueryBuilder<T> { where<K extends keyof T>(column: K, value: T[K]): this; where<K extends keyof T>(column: K, operator: string, value: any): this; where(condition: Partial<T>): this; select<K extends keyof T>(...columns: K[]): QueryBuilder<Pick<T, K>>; orderBy(column: keyof T, direction?: "asc" | "desc"): this; limit(count: number): this; offset(count: number): this; first(): Promise<T | null>; get(): Promise<T[]>; count(): Promise<number>; insert(data: Omit<T, "id">): Promise<T>; update(data: Partial<T>): Promise<number>; delete(): Promise<number>; } </code> ===== 11.8 工具与资源 ===== ==== 11.8.1 自动生成声明 ==== <code bash> # 从TypeScript源码生成声明 tsc --declaration --emitDeclarationOnly # 使用dts-bundle打包声明 npx dts-bundle --name mylib --main dist/index.d.ts # 从JSDoc生成 tsc --allowJs --declaration --emitDeclarationOnly </code> ==== 11.8.2 测试声明文件 ==== <code typescript> // mylib-tests.ts import { add, multiply, Calculator } from "mylib"; // $ExpectType number const sum = add(1, 2); // $ExpectError add("1", "2"); // 测试类 const calc = new Calculator(); // $ExpectType number calc.multiply(5); </code> ===== 11.9 小结 ===== 类型声明文件是TypeScript生态的关键组成部分: 1. **声明语法**:declare关键字用于声明变量、函数、类、枚举等 2. **模块模式**:支持全局库、模块库和UMD模式的声明 3. **高级类型**:条件类型、映射类型、泛型约束等高级特性 4. **发布策略**:与npm包一起发布或提交到DefinitelyTyped 5. **最佳实践**:避免any、添加文档注释、保持版本兼容 掌握声明文件编写对于TypeScript开发者来说是一项重要技能,特别是在使用JavaScript库或为库添加TypeScript支持时。
typescript/第十一章类型声明文件.txt
· 最后更改:
2026/02/03 22:33
由
127.0.0.1
页面工具
显示页面
过去修订
反向链接
回到顶部