TS 中的类型声明文件在 ts 项目中,我们能看到一些 .d.ts文件,它们是类型声明文件,d 可以看成是 declar
在 ts 项目中,我们能看到一些 .d.ts文件,它们是类型声明文件,d 可以看成是 declare(声明)的意思。类型声明文件大致可分为以下介绍的三类:
内置类型声明
在 ts文件里我们使用 document
等对象会有类型提示:
是因为 ts 提供了一些内置的类型声明:
看该文件的路径可以知道它是存储在 VS Code 里的,如果使用的是其它编译器,只要全局安装过了 ts,编译器就会去搜寻内置的 .d.ts 文件。
可以看到,在 .d.ts 文件中,顶级声明都以 declare
作为开头,这样其它地方使用时就无需额外引入了。但是如果在顶级声明中还使用了 export
,比如:
export declare interface ILoginReq extends IClientSetting {
scope?: string
}
或者直接省略 declare
:
export interface ILoginReq extends IClientSetting {
scope?: string
}
那么在其它地方使用类型 ILoginReq
时就需要先引入。
指定内置声明文件
这些内置的 .d.ts 在 ts 的 GitHub 仓库中可以查看:
有时候我们编写的一些代码,比如使用 promise.finally
时会遇到报错:
就可以通过修改 tsconfig.json 文件的 compilerOptions.lib
配置,lib 的可选值可查看官方文档:
{
"compilerOptions": {
"lib": ["ES2015", "ES2016", "DOM", "ES2018"]
}
}
"ES2018"
意味着使用 es2018.d.ts,其 中引用了 es2018.promise.d.ts:
在 es2018.promise.d.ts 中就定义了 Promise
的 finally
属性:
其实也可以直接更改 compilerOptions.target
为 "ES2018"
,compilerOptions.lib
会根据 target
自动配置。顺便一提,我们无需担心浏览器是否能识别运行 ES2018 的语法,因为项目中最终 ts 一般是通过 babel 转换的。
外部定义的类型声明
有些第三方库,如 axios,安装后其本身就有类型声明文件 index.d.ts:
而另一些,如 lodash,在使用 npm 安装后则没有 .d.ts 文件,直接引入会报错:
我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。提示里已经告诉了我们解决办法:
npm i --save-dev @types/lodash
之后就能在 ts 文件中正常使用 lodash 了。而这个安装包,来自于 DefinitelyTyped,是一个公共的存放类型声明的库。
自己定义类型声明
如果找不到现成的类型声明文件,就需要我们自己定义了。比如,我们可以自己在项目中新建个 lodash 的类型声明文件 index.d.ts,ts 编译器会扫描并加载项目中所有的 ts 声明文件(如果执行报错就把 index.d.ts 放到 node_modules\lodash 中):
declare module 'lodash' {
export function cloneDeep(any): any
}
declare module
用于声明模块,其后在 {}
中使用 export
导出了模块内的 cloneDeep
函数 function cloneDeep(any): any
。这样就能在 ts 文件中使用 lodash 的 cloneDeep
方法了:
import _ from 'lodash'
const obj = {
name: 'Jay'
}
const newObj = _.cloneDeep(obj)
上面是声明了模块,还可以声明变量、函数、类和文件:
declare let bianlian: string
declare function fn(): void
declare class Lei {
constructor(public name: string)
}
declare module '*.jpg'
declare module '*.mjs'
但是,如果声明的是 interface
等只存在于 ts 的类型系统中的,通常不需要在 interface
前加上 declare
关键字,ts 编译器会自动识别并合并相同名称的 interface
声明。
declare
也可以直接在 ts 文件中使用,比如我们想使用 jQuery,一种常见的方式是在 html 中通过 <script>
标签引入 jQuery,然后就可以使用全局变量 $
或 jQuery
了。但是在 ts 中,编译器并不知道 $
或 jQuery
是什么东西。我们可以使用 declare
来定义它的类型:
declare var jQuery: (selector: string) => any
jQuery('#foo')
declare var
并没有真的定义一个变量,只是定义了全局变量 jQuery 的类型,仅仅会用于编译时的检查,在编译结果中会被删除。它编译结果是:
jQuery('#foo')
转载自:https://juejin.cn/post/7368035468611977231