TypeScript 类型声明的三种来源
你是否写过这样的代码,比如,我们在声明一个div
节点时会这样写:
const div: HTMLDivElement = document.createElement('div')
这里的HTMLDivElement
,我们并没有声明,这是从哪里来的呢?
还有,我们在使用第三方库的时候,这些库文件明明是用 javascript 写的,为什么也会有类型提示呢?
下面将一一解答上面的问题。
Typescript
内置的类型声明文件
我们会经常用到浏览器环境相关的的HTMLElement
、Event
类型信息,还有 JS 引擎提供的Promise
、Date
、RegExp
等。
这些类型声明文件放在哪呢?
TypeScript 包下有个 lib 目录,里面有一堆 lib.xx.d.ts 的类型声明文件,这就是 TS 内置的一些类型声明。
因为这些只是声明类型,而没有具体的 JS 实现,TS 就给单独设计了一种文件类型,也就是 d.ts
, d
是 declare
的意思。
比如 lib.dom.d.ts
里的类型声明:
因为这些类型声明文件是 ts 内置的,所以需要在tsconfig.json
配置一下就可以用了:
Typescript 内置的类型声明文件只有 DOM 和 ES 的。因为 JS 的 API 还有浏览器的 API 都是有标准的,那自然可以按照标准来定义类型。其余环境的 API 没有标准,经常变,自然就没法内置了,比如 node。
@types 包存放类型声明文件
node
等环境的 API 因为没有标准而没有被 Typescript 内置,但 Typescript 同样也支持了这些环境的类型声明的配置。它是通过 node_modules下的 @types/node
的包来支持的,即 node 的类型声明文件放在 @types/node
下面。
Tyepscript 会先加载内置的 lib 的类型声明,然后再去查找 @types
包下的类型声明。
@types
包是在 DefinitelyTyped 这个项目下统一管理的,想创建一个 @types
包的话要去看一下他们的文档。
除了给 node 等环境的 API 加上类型声明外,@types
包还有一种用途,就是给一些 JS 的包加上类型声明。
比如,有一个库的代码原来是用 Javascript 书写的,在 Typescript 工程中使用了这个库,此时如果这个库也需要有类型支持,那么就需要单独写一个 @types/xxx
的包来声明这个库的 ts 类型,然后发布到统一的DefinitelyTyped
,最后在工程中安装npm install @types/xxx -D
,这样 JS 库也会得到类型支持。
如果这个库本身是用 Tpyescript 写的,那编译的时候就可以开启 compilerOptions.declaration
,来生成 d.ts
文件:
然后在 package.json
里配置 types
来指定 d.ts
的位置:
至此,Typescript 内置的 DOM 和 ES 的类型声明,其他环境如 node,以及一些第三方库的类型声明我们都知道怎么使用了。
自己写的类型声明文件
在变量声明时我们就可以定义类型,如:
interface Person {
name: string;
age: number;
}
const : Person = {
name: 'xiaoming',
age: 13
}
除了这种方式外,TS 也支持通过 declare 单独声明类型,且存放类型声明的文件后缀是 d.ts
。
现在我们声明一个变量calculator
,这个变量是一个函数,同时这个函数还有两个属性plus
和minus
type Operator = 'plus' | 'minus'
interface Icalculator {
(operator: Operator, numbers: number[]): number
plus(numbers: number[]): number
minus(numbers: number[]): number
}
declare const calculator: Icalculator
要使这个类型声明文件生效,需要在tsconfig.json
配置 include
, exclude
,files
:
- include 用来指定哪些 ts 文件需要被编译,*表示任意目录, 表示任意文件
- exclude 不需要被编译的文件目录
- files 指定被编译文件的列表,只有需要编译的文件少时才会用到,不能用通配符,只能是具体的路径
// tsconfig.json
"files": ["calculator.d.ts"]
Typescript 在编译的时候,会分别加载内置的 lib
,@types
下的,还有 include
和 files
的文件,进行类型检查。
这就是 Typescript 类型声明的三种来源。
总结
通过类型声明文件,TypeScript在编译时做类型检查,TypeScript 有三种存放类型声明的地方:
- lib: 内置的类型声明,包含 DOM 和 ES 的;
- @types: npm 包的类型声明;
- 开发者写的代码:通过 include + exclude 还有 files 指定,还有就是在定义变量时写的类型定义;
转载自:https://juejin.cn/post/7244043482770686010