阿里云主机折上折
  • 微信号
Current Site:Index > Type declaration file (.d.ts)

Type declaration file (.d.ts)

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

Basic Concepts of Type Declaration Files (.d.ts)

Type declaration files are special files in TypeScript used to describe the types of JavaScript libraries or modules. They have the .d.ts extension, contain no actual implementation code, and only include type information. When using libraries written in pure JavaScript, .d.ts files provide TypeScript with the necessary type-checking support.

// example.d.ts
declare module "some-library" {
  export function doSomething(value: string): number;
  export interface Options {
    timeout?: number;
    retries?: number;
  }
}

Why Type Declaration Files Are Needed

The JavaScript ecosystem has a vast number of libraries not written in TypeScript. Type declaration files allow these libraries to benefit from type checking when used in TypeScript projects. They act as a bridge between JavaScript code and TypeScript's type system, offering the following advantages:

  1. Code completion and intelligent hints
  2. Compile-time type checking
  3. Better documentation support
  4. Refactoring safety

Three Sources of Type Declaration Files

Built-in Type Declarations

TypeScript comes with type declarations for certain libraries, such as DOM APIs and ECMAScript built-in objects. These declarations are included in the TypeScript installation package.

// Built-in lib.dom.d.ts contains DOM types
document.getElementById("app"); // Automatically provides type hints

Third-Party Type Declarations

Provided by the DefinitelyTyped project via @types packages. When installing a package like @types/react, you are essentially installing the type declaration files for the React library.

npm install --save-dev @types/lodash

Custom Type Declarations

Developers can create .d.ts files for their own JavaScript code or for third-party libraries lacking type declarations.

// custom.d.ts
declare module "my-untyped-module" {
  export const version: string;
  export function calculate(a: number, b: number): number;
}

Syntax of Type Declaration Files

Declaring Variables

declare const PI: number;
declare let config: {
  apiUrl: string;
  debug: boolean;
};

Declaring Functions

declare function greet(name: string): string;
declare function fetchData(url: string, options?: { timeout?: number }): Promise<any>;

Declaring Classes and Interfaces

declare class User {
  constructor(name: string);
  id: number;
  getName(): string;
}

declare interface Point {
  x: number;
  y: number;
  distanceTo(other: Point): number;
}

Declaring Modules

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

declare module "jquery" {
  interface JQuery {
    modal(options?: any): JQuery;
  }
  function $(ready: () => void): void;
  export = $;
}

Global Declarations vs. Module Declarations

Global Declarations

Global declarations are available in any file without needing to import them. They are typically used to extend global objects or declare global variables.

// global.d.ts
declare namespace NodeJS {
  interface ProcessEnv {
    NODE_ENV: 'development' | 'production';
    API_KEY: string;
  }
}

Module Declarations

Module declarations require import statements and are used to describe the types of specific modules.

// module.d.ts
declare module "my-module" {
  export function init(config: { debug: boolean }): void;
  export class Logger {
    log(message: string): void;
  }
}

Type Merging and Augmentation

TypeScript allows merging type declarations with the same name, which is useful for extending existing types.

Interface Merging

// original.d.ts
interface User {
  name: string;
}

// extension.d.ts
interface User {
  age: number;
}

// Result after merging:
// interface User {
//   name: string;
//   age: number;
// }

Namespace Merging

// original.d.ts
namespace Utils {
  export function formatDate(date: Date): string;
}

// extension.d.ts
namespace Utils {
  export function formatCurrency(amount: number): string;
}

Conditional Types and Advanced Types

Advanced TypeScript features can also be used in .d.ts files.

declare type Nullable<T> = T | null;
declare type Record<K extends keyof any, T> = {
  [P in K]: T;
};

declare function getProperty<T, K extends keyof T>(obj: T, key: K): T[K];

Common Issues and Solutions

Handling Untyped Modules

When using modules without type declarations, you can quickly declare them as any:

declare module "untyped-module";

Extending Third-Party Types

import { OriginalType } from "some-library";

declare module "some-library" {
  interface OriginalType {
    newMethod(): void;
  }
}

Avoiding Global Pollution

Use module declarations to avoid polluting the global scope:

// Not recommended
declare const myGlobal: string;

// Recommended
declare module "my-globals" {
  export const myGlobal: string;
}

Testing Type Declaration Files

After creating .d.ts files, validate their correctness:

  1. Create test files to import the declarations
  2. Check if type inference is correct
  3. Verify edge cases
// test.ts
import { calculate } from "my-untyped-module";

const result = calculate(1, 2); // Should correctly infer as number type

Publishing Type Declaration Files

If you create type declarations for a library, publish them in the following ways:

  1. Include them with the library code (using the types field)
  2. Publish to DefinitelyTyped
  3. Release as a separate @types package
// package.json
{
  "name": "my-library",
  "types": "dist/index.d.ts",
  "files": ["dist"]
}

Best Practices

  1. Keep declaration files synchronized with implementations
  2. Use precise types instead of any
  3. Provide documentation comments for complex types
  4. Organize related declarations into namespaces
  5. Prefer interfaces over type aliases
  6. Consider backward compatibility
/**
 * Basic user information
 */
interface User {
  /**
   * Unique user identifier
   */
  id: number;
  /**
   * User display name
   */
  name: string;
}

Tools and Ecosystem

dts-gen

A tool for automatically generating type declaration files:

npx dts-gen -m <module-name>

TypeScript Compiler Options

Relevant configurations:

{
  "compilerOptions": {
    "typeRoots": ["./typings", "./node_modules/@types"],
    "types": ["node", "lodash"],
    "declaration": true
  }
}

Complex Scenario Examples

Declaring React Higher-Order Components

import * as React from 'react';

declare module 'react' {
  function memo<T extends React.ComponentType<any>>(
    Component: T,
    propsAreEqual?: (prevProps: React.ComponentProps<T>, nextProps: React.ComponentProps<T>) => boolean
  ): T;
}

Declaring Vue Plugins

import { PluginObject } from 'vue';

declare module 'vue/types/vue' {
  interface Vue {
    $myPlugin: {
      showToast(message: string): void;
    };
  }
}

declare const MyPlugin: PluginObject<{ options: any }>;
export default MyPlugin;

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

如果侵犯了你的权益请来信告知我们删除。邮箱: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 ☕.