阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 外部模块声明

外部模块声明

作者:陈川 阅读数:49015人阅读 分类: TypeScript

外部模块声明

TypeScript 的外部模块声明允许开发者描述非 TypeScript 编写的库或模块的形状。当使用 JavaScript 库时,这些声明文件(通常以 .d.ts 结尾)提供了类型信息,使得 TypeScript 能够进行类型检查并提供智能提示。

声明文件基础

外部模块声明通常放在 .d.ts 文件中。这些文件不包含实现,只包含类型信息。例如,对于一个简单的 JavaScript 库:

// math.js
function add(a, b) {
  return a + b;
}

对应的声明文件可能是:

// math.d.ts
declare function add(a: number, b: number): number;

模块声明语法

完整的模块声明使用 declare module 语法。例如,为流行的 lodash 库创建声明:

declare module 'lodash' {
  export function chunk<T>(array: T[], size?: number): T[][];
  export function compact<T>(array: T[]): T[];
  // 更多方法声明...
}

全局扩展

有时需要扩展全局作用域中的类型。例如,为 String 添加自定义方法:

// global.d.ts
declare global {
  interface String {
    toTitleCase(): string;
  }
}

然后在代码中实现:

String.prototype.toTitleCase = function() {
  return this.replace(/\w\S*/g, txt => 
    txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
  );
};

第三方库的类型定义

对于流行的 JavaScript 库,通常可以通过 DefinitelyTyped 获取类型定义。安装方式:

npm install --save-dev @types/lodash

复杂模块示例

考虑一个假设的图表库 chart-lib,它导出一个 Chart 类和多个接口:

declare module 'chart-lib' {
  export interface ChartOptions {
    width?: number;
    height?: number;
    theme?: 'light' | 'dark';
  }

  export interface DataPoint {
    x: number;
    y: number;
    label?: string;
  }

  export class Chart {
    constructor(container: HTMLElement, options?: ChartOptions);
    render(data: DataPoint[]): void;
    destroy(): void;
  }
}

命名空间合并

当模块既有默认导出又有命名导出时,可以这样声明:

declare module 'complex-module' {
  export function helper(): void;
  
  namespace complexModule {
    export const version: string;
    export interface Config {
      debug: boolean;
    }
  }
  
  export default complexModule;
}

条件类型和模块

在高级场景中,可能需要根据环境变量改变模块类型:

declare module 'config' {
  export const apiUrl: string;
  export const timeout: number;
  
  if (process.env.NODE_ENV === 'development') {
    export const debugMode: true;
  }
}

模块重定向

有时需要将模块导入重定向到其他位置:

declare module 'old-library' {
  import * as newLibrary from 'new-library';
  export = newLibrary;
}

处理 CommonJS 和 AMD

对于不同的模块系统,声明方式略有不同。CommonJS 模块:

declare module 'legacy-module' {
  function createInstance(options?: object): any;
  export = createInstance;
}

类型推断增强

当模块导出复杂对象时,可以使用类型推断:

declare module 'geometry' {
  export interface Point {
    x: number;
    y: number;
  }
  
  export interface Circle {
    center: Point;
    radius: number;
  }
  
  export function createCircle(x: number, y: number, radius: number): Circle;
  export function area(circle: Circle): number;
}

动态模块加载

对于动态导入的模块,可以这样声明:

declare module 'dynamic/*' {
  const content: {
    default: React.ComponentType;
    metadata: object;
  };
  export default content;
}

处理 CSS 和资源文件

在模块系统中处理非 JavaScript 资源:

declare module '*.css' {
  const classes: { [key: string]: string };
  export default classes;
}

declare module '*.png' {
  const value: string;
  export default value;
}

模块版本控制

处理不同版本的模块类型:

declare module 'some-library/v1' {
  export function oldAPI(): void;
}

declare module 'some-library/v2' {
  export function newAPI(): void;
}

全局变量声明

虽然不是严格意义上的模块,但全局变量声明也类似:

declare const __VERSION__: string;
declare const __DEV__: boolean;

模块扩展模式

扩展已有模块的类型:

import { Original } from 'original-module';

declare module 'original-module' {
  interface Original {
    newMethod(): void;
  }
}

复杂泛型模块

带有泛型的模块声明示例:

declare module 'generic-storage' {
  export interface Storage<T = any> {
    get(key: string): Promise<T | undefined>;
    set(key: string, value: T): Promise<void>;
    delete(key: string): Promise<void>;
  }
  
  export function createStorage<T>(options?: { prefix?: string }): Storage<T>;
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌