详解如何编写一个Typescript的类型声明文件

作者:闭包旅人

时间:2026-10-30

浏览:138

本文详细讲解如何为JavaScript库编写TypeScript类型声明文件。通过自定义calculator库和axios库两个实例,演示如何定义函数、接口、重载及模块导出。涵盖d.ts文件创建、tsconfig配置、模块解析注意事项,以及如何将声明发布至@types供npm安装使用,帮助开发者实现类型安全。

文章目录

类型声明文件概述

当前任务是为一个JavaScript编写的库创建对应的类型声明文件。

该库导出了一个函数calculator,其具体功能如下所示。

参考calculator.js文件内容。

// operator: 只能是 plus | minus
function calculator(operator, numbers) {
  console.log(operator, numbers)
  return
}
calculator.plus = (numbers) => {
  return numbers
}
calculator.minus = (numbers) => {
  return numbers
}
export default calculator

首先分析calculator的结构。

该函数接收两个参数:第一个参数限定为plus或minus,第二个参数为数字数组。

此外,该函数还包含两个属性plus和minus,它们均接收数字数组作为参数。

自定义库类型声明实战

接下来逐步完善类型声明文件。

第一步,创建calculator.d.ts文件。由于calculator本质是一个函数,首先定义函数类型:

见calculator.d.ts文件内容。

type IOperator = 'plus' | 'minus'
type ICalculate = (operator: IOperator, numbers: number[]) => number
declare const calculator: ICalculate
export default calculator

配置tsconfig.json:

"files": ["calculator.d.ts"]

见index.ts文件内容。

类型声明文件概述

此时,编写的类型声明文件已生效。

注意,在index.ts中引入calculator.js的函数时,calculator.d.ts文件中必须包含export default calculator,否则将报错提示calculator.d.ts不是一个模块。

类型声明文件概述

然而,当尝试访问该函数的属性时,会出现报错。

类型声明文件概述

这是因为仅声明了函数,而calculator还包含两个属性方法。解决方法是使用interface:

interface Icalculator {
  (operator: Operator, numbers: number[]): number
  plus(numbers: number[]): number
  minus(numbers: number[]): number
}

类型声明文件概述

至此任务完成。最后将声明文件提交至@types组织,并通过npm install @types/calculator下载,TypeScript即可自动读取此类声明文件。

注意:提交至@types时,类型文件命名必须为index.d.ts。

此时引入方式变为import calculator from 'calculator'。

复杂库类型定义示例

接下来查看一个axios库的类型定义文件编写方法。对axios类型声明文件进行精简,保留核心部分。

// 定义请求头的格式,即 key 只能是字符串,value 是一个联合类型 string | number | boolean
export type AxiosRequestHeaders = Record<string, string | number | boolean>;
// 定义了响应头的格式,即 key 和 value只能是字符串,同时利用 &(交叉类型) 把多个类型合并成一个类型
export type AxiosResponseHeaders = Record<string, string> & {
  "set-cookie"?: string[]
};
// 对请求的参数进行转换,此处对应的就是转换函数
export interface AxiosRequestTransformer {
  (data: any, headers?: AxiosRequestHeaders): any;
}
// 定义了所有请求方法的类型
export type Method =
  | 'get' | 'GET'
  | 'delete' | 'DELETE'
  | 'head' | 'HEAD'
  ...
// 定义了所有返回数据的类型,可以是二进制,也可以是json对象
export type ResponseType =
  | 'arraybuffer'
  | 'blob'
  | 'document'
  | 'json'
  ...
// 请求配置AxiosRequestConfig是一个接口,接口传入了一个泛型,这个泛型就可以流入到里面的属性或值里面。
export interface AxiosRequestConfig<D = any> {
  url?: string;
  method?: Method | string;
  baseURL?: string;
  headers?: AxiosRequestHeaders;
  params?: any;
  data?: D;
  responseType?: ResponseType;
  ...
}
// 请求返回的数据类型,定义了一个interface,里面有data,status等,同时传入了一个泛型,这个泛型可以流入到data里面,这样我就定义了data的类型
export interface AxiosResponse<T = any, D = any>  {
  data: T;
  status: number;
  statusText: string;
  headers: AxiosResponseHeaders;
  config: AxiosRequestConfig<D>;
  request?: any;
}
// 定义了一个Axios的类,这个类定义了构造函数constructor,拦截器interceptors,以及一些调用方法get/post等
export class Axios {
  constructor(config?: AxiosRequestConfig);
  defaults: AxiosDefaults;
  interceptors: {
    request: AxiosInterceptorManager<AxiosRequestConfig>;
    response: AxiosInterceptorManager<AxiosResponse>;
  };
  get<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
  post<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  ...
}
// AxiosPromise 继承于 Promise<AxiosResponse<T>>,Promise<AxiosResponse<T>>里面传入了泛型,这样泛型流入到AxiosResponse里面
export interface AxiosPromise<T = any> extends Promise<AxiosResponse<T>> {
}
// 定义了一个Axios实例的接口
export interface AxiosInstance extends Axios {
  (config: AxiosRequestConfig): AxiosPromise;
  (url: string, config?: AxiosRequestConfig): AxiosPromise;
}
export interface AxiosStatic extends AxiosInstance {
  create(config?: AxiosRequestConfig): AxiosInstance;
  Axios: typeof Axios;
  ...
}
declare const axios: AxiosStatic;
export default axios;

首先引入import axios from 'axios',其类型为AxiosStatic,该类型包含create方法:

export interface AxiosStatic extends AxiosInstance {
  create(config?: AxiosRequestConfig): AxiosInstance;
  Axios: typeof Axios;
  ...
}

执行create方法后,返回类型为AxiosInstance的变量:

export interface AxiosInstance extends Axios {
  (config: AxiosRequestConfig): AxiosPromise;
  (url: string, config?: AxiosRequestConfig): AxiosPromise;
}

该变量首先是一个函数,支持两种调用方式:(config: AxiosRequestConfig): AxiosPromise; 或 (url: string, config?: AxiosRequestConfig): AxiosPromise;。同时它继承自Axios类型,拥有get、post等方法,因此具备如下使用方式:

import axios from 'axios'
const axiosInstance = axios.create()
// 发送请求的三种方式
axiosInstance({ url: 'test.url'})
axiosInstance(url: 'test.url', config: { method: 'get' })
axiosInstance.get('test.url')

本文关于如何编写TypeScript类型声明文件的介绍到此结束。更多相关TypeScript类型声明文件内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章