声明文件
从类型type角度分为:基本类型(string、number、boolean等)及其混合;复杂类型(class、function、object)及其混合(比如说又是class又是function)。
从代码有效范围分为:全局变量、模块变量和又是全局变量又是模块变量的。
从定义文件来说:自己写的
.d.ts
文件和扩展别人写的.d.ts
文件。
支持语法
声明文件应用场景
主要是为了解决在ts中第三方组件库或者插件中,第三方库引用的问题。
例如,代码中用到了jQuery
,需要到 .d.ts
文件中声明,不然TS语法会报找不到全局变量 jquery
和$
对象;
// shime-global.d.ts
然后在改目录下所有ts中使用 jQuery
, $
对象是,ts便不会报错。
上例中,declare var 并没有真的定义一个变量,只是定义了全局变量 jQuery 的类型,仅仅会用于编译时的检查,在编译结果中会被删除。它编译结果是:
补充:上面声明文件为什么是.d.ts
,这是ts模块解析规定的,先从.ts
文件中查找,然后再查找 .d.ts
文件中查找。
先让我们看看在工程中一般有哪些声明:
我们经常这样配置全局变量,如果第三方库没有声明,当前代码中没有定义的,都需要声明。
vue 模块的声明
全局变量 模块
那么有些同学就要问了,我们用的很多npm,npm install
之后,好像也没有声明,在ts中使用编译也没有报错啊。那是因为npm中已经声明了。
书写声明文件
当一个第三方库没有提供声明文件时,我们就需要自己书写声明文件了。
第三方库有以下几种使用场景
全局变量:通过 标签引入第三方库,注入全局变量
npm 包:通过 import foo from 'foo' 导入,符合 ES6 模块规范
UMD 库:既可以通过 标签引入,又可以通过 import 导入
直接扩展全局变量:通过 标签引入后,改变一个全局变量的结构
在 npm 包或 UMD 库中扩展全局变量:引用 npm 包或 UMD 库后,改变一个全局变量的结构
模块插件:通过 或 import 导入后,改变另一个模块的结构
全局变量的声明
全局变量的声明主要用以下几种
declare var
声明全局变量declare function
声明全局方法declare class
声明全局类declare enum
声明全局枚举类型declare namespace
声明(含有子属性的)全局对象interface
和type
声明全局类型
举个例子:声明一个class 对象 Animal
npm包的声明
一般来说,npm 包的声明文件可能存在于两个地方:
与该 npm 包绑定在一起。判断依据是
package.json
中有 types 字段,或者有一个index.d.ts
声明文件。这种模式不需要额外安装其他包,是最为推荐的,所以以后我们自己创建 npm 包的时候,最好也将声明文件与 npm 包绑定在一起。
发布到 @types 里。我们只需要尝试安装一下对应的 @types 包就知道是否存在该声明文件,安装命令是
npm install @types/foo --save-dev
。这种模式一般是由于 npm 包的维护者没有提供声明文件,所以只能由其他人将声明文件发布到 @types 里了。
假如以上两种方式都没有找到对应的声明文件,那么我们就需要自己为它写声明文件了.
有两种方案,一种自己写@types/xxx
,发布上去。另一个直接在工程目录下声明,建议新建一个目录types
,声明文件放在types
中
npm中声明和全局变量声明的区别
npm 包的声明文件与全局变量的声明文件有很大区别。在 npm 包的声明文件中,使用 declare
不再会声明一个全局变量,而只会在当前文件中声明一个局部变量。只有在声明文件中使用 export
导出,然后在使用方 import
导入后,才会应用到这些类型声明。
当然也可以混用
上面 Axios
就是这样做的。
UMD库中的声明
在 npm 包或 UMD 库中扩展全局变量
对于 npm 包或 UMD 库,如果导入此库之后会扩展全局变量,则需要使用另一种语法在声明文件中扩展全局变量的类型,那就是 declare global
声明模块插件
发布声明文件
两种方式
将声明文件和源码放在一起
发布到
@types
中
将声明文件和源码放在一起
自动生成,tsc自动生成
手动声明
如果是手动写的声明文件,那么需要满足以下条件之一,才能被正确的识别:
给
package.json
中的types
或typings
字段指定一个类型声明文件地址在项目根目录下,编写一个
index.d.ts
文件针对入口文件(
package.json
中的main
字段指定的入口文件),编写一个同名不同后缀的.d.ts
文件
如果没有指定types
或typings
,那么就会在根目录下寻找 index.d.ts
文件,将它视为此库的类型声明文件。
如果没有找到 index.d.ts
文件,那么就会寻找入口文件(package.json
中的 main
字段指定的入口文件)是否存在对应同名不同后缀的 .d.ts
文件。
如果还是不存在,那么就会寻找是否存在 lib/index.d.ts
文件。假如说连 lib/index.d.ts
都不存在的话,就会被认为是一个没有提供类型声明文件的库了。
参考
Last updated