ts 声明文件

引入/创建声明文件

在使用 TypeScript 写程序的时候,可能会需要使用到 JavaScript 库,因为历史遗留问题,现在非常多的第三方库依然是用 JavaScript 进行编写,但是大多数情况下,库的所有者已经帮你写好了 TypeScript 声明文件,即 .d.ts 文件。

还有一些情况是库中并没有附带 ts 声明文件,但是可以通过:

1
npm i @types/xxx

进行下载该类型的库的声明文件。

上面两种方法都是用在别人已经帮你编写了声明文件的情况下,但是如果上面两种方式都无效,怎么自行编写声明文件呢?

假设现在要编写 wow.js 的声明文件,只需以下两步即可:

  1. 在 src 下新建 types 文件夹,在 types 下新建 wow.d.ts 文件

  2. 在 wow.d.ts 中添加如下内容:declare module "wow.js"

之后即可正常导入 wow.js 了。

那如果想要在原有库的基础上拓展一些类型该怎么办呢?看下面两个例子。


拓展

axios

在使用 axios 库时,我们通常会在响应拦截器中返回 AxiosResponse.data,但是这样的话,在请求完成获取响应数据时会造成类型错误:

1
2
3
4
5
6
7
// 响应拦截器
request.interceptors.response.use((response: AxiosResponse) => {
return response.data
})

// 发起请求
request({}).then((res: AxiosResponse) => {});

这里的 res 实际上是 AxiosResponse.data,但类型检查时它的类型仍然是 AxiosResponse,这就造成了错误。

那要怎么解决呢?我们可以拓展 AxiosResponse 接口。

在 src/types 下新建 axios.d.ts 文件,添加入下内容:

1
2
3
4
5
6
7
8
9
10
import "axios"

declare module 'axios' {
export interface AxiosResponse<T = any> {
code: number;
data?: T;
message?: string;
[key: string]: any;
}
}

注意: 一定要在文件顶部引入 “axios”,否则就是重写 axios 的声明文件了。

如果想要明确 data 的类型,可以这样写:

1
2
3
4
5
6
7
8
9
10
11
import { AxiosResponse } from "axios";

interface Res {
name: string;
age: number;
}

request({}).then((res: AxiosResponse<Res>) => {
res.code;
res.data.name;
})

pinia

使用 pinia 时为 state 声明类型。

在 src/types 下新建 pinia.d.ts 文件,添加如下内容:

1
2
3
4
declare interface UserInfoState {
name: string;
age: number;
}

之后在创建仓库时可直接使用以上的接口。

1
2
3
4
5
6
7
8
import { defineStore } from 'pinia';

const userInfo = defineStore("userInfo", {
state: (): UserInfoState => ({
name: "",
age: 0
})
})