梳理一下 @types/xxx
一、TypeScript 怎么知道库的类型?
ypeScript 在编译时需要知道函数、变量、对象的 类型 才能做检查。对于第三方库,类型信息有三种来源:
-
库本身自带类型声明
-
比如 axios、vue、react 等现代库,源代码里就自带 index.d.ts 类型声明文件。
-
这种情况下,你只要安装库本身就行,TS 就能找到类型信息。
-
npm install axios
import axios from "axios";
axios.get("/api"); // axios 自带类型推断
- DefinitelyTyped 提供的 @types/xxx 包
-
有些库(比如早期写的 JS 库:lodash-es、jquery、express)没写 TypeScript 类型。
-
社区把类型声明写好后,统一放到 DefinitelyTyped 仓库,然后发布到 npm 的 @types 命名空间下。
-
这就是你看到的:
npm install lodash-es
npm install -D @types/lodash-es
TypeScript 会自动去 node_modules/@types 文件夹里找对应的类型声明。
-
自己写 .d.ts 声明文件
- 如果某个库既没有自带类型,也没有 @types/xxx,你就得自己写类型声明文件。
写法比如:
// types/some-lib.d.ts
declare module "some-lib" {export function foo(bar: string): number;
}
二、为什么有的需要 @types,有的不用?
总结下来就是:
-
现代库(新出的库) → 一般直接在项目里自带 .d.ts 文件 → 不用装 @types
-
老库(纯 JS 写的库) → 没有类型 → 社区补充 @types/xxx 包 → 要单独装 @types
-
没人维护的库 → 可能没有任何类型声明 → 只能自己写 .d.ts
三、TypeScript 查找类型的优先级
当你写 import _ from “lodash-es” 时,TypeScript 按以下顺序查找类型:
-
库内部的 package.json 里是否声明了 types 或 typings 字段
-
指向一个 .d.ts 文件。
-
比如 axios/package.json 里有 “types”: “index.d.ts”。
-
-
库根目录是否有 index.d.ts
- 如果有,就用这个文件。
-
是否安装了对应的 @types/xxx 包
- TypeScript 会自动去 node_modules/@types/xxx 目录找。
-
没有找到
- TS 把库当成 any,你就失去了类型提示和检查。
四、举几个例子
库名 | 是否自带类型 | 是否需要 @types |
---|---|---|
axios | ✅ 自带 | ❌ 不需要 |
react | ✅ 自带(17 之后) | ❌ 不需要 |
vue | ✅ 自带 | ❌ 不需要 |
lodash-es | ❌ 没有 | ✅ 需要 @types/lodash-es |
express | ❌ 没有 | ✅ 需要 @types/express |
jquery | ❌ 没有 | ✅ 需要 @types/jquery |