阿里云主机折上折
  • 微信号
Current Site:Index > External module declaration

External module declaration

Author:Chuan Chen 阅读数:49016人阅读 分类: TypeScript

External Module Declarations

TypeScript's external module declarations allow developers to describe the shape of libraries or modules not written in TypeScript. When using JavaScript libraries, these declaration files (typically ending with .d.ts) provide type information, enabling TypeScript to perform type checking and offer intelligent code completion.

Basics of Declaration Files

External module declarations are usually placed in .d.ts files. These files contain no implementation—only type information. For example, for a simple JavaScript library:

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

The corresponding declaration file might be:

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

Module Declaration Syntax

Full module declarations use the declare module syntax. For example, creating a declaration for the popular lodash library:

declare module 'lodash' {
  export function chunk<T>(array: T[], size?: number): T[][];
  export function compact<T>(array: T[]): T[];
  // More method declarations...
}

Global Augmentation

Sometimes you need to extend types in the global scope. For example, adding a custom method to String:

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

Then implement it in your code:

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

Type Definitions for Third-Party Libraries

For popular JavaScript libraries, type definitions are often available via DefinitelyTyped. Installation method:

npm install --save-dev @types/lodash

Complex Module Example

Consider a hypothetical chart library chart-lib that exports a Chart class and several interfaces:

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;
  }
}

Namespace Merging

When a module has both default and named exports, you can declare it like this:

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

Conditional Types and Modules

In advanced scenarios, you might need to change module types based on environment variables:

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

Module Redirection

Sometimes you need to redirect module imports to another location:

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

Handling CommonJS and AMD

Declarations differ slightly for different module systems. For CommonJS modules:

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

Type Inference Enhancement

When modules export complex objects, you can use type inference:

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;
}

Dynamic Module Loading

For dynamically imported modules, declare them like this:

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

Handling CSS and Asset Files

Handling non-JavaScript resources in module systems:

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

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

Module Versioning

Handling types for different module versions:

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

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

Global Variable Declarations

Though not strictly modules, global variable declarations are similar:

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

Module Augmentation Patterns

Extending types of existing modules:

import { Original } from 'original-module';

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

Complex Generic Modules

Example of a module declaration with generics:

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

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.