TS-08 声明文件、模块解析
为什么需要声明文件
当引入了全局的库之后,比如jQuery
库,会在ts
文件中使用$
符,在ts
文件中直接使用是会提示找不到文件的,是因为没有声明文件;
声明文件的查找
可以在tsconfig.json
文件中,添加include
字段,配置声明文件的路径,如果不配置,则会查找所有文件夹下面的.d.ts
文件;
{
"include": [
"./scr/**/*.ts", // 代表src下面某个文件夹下面的声明文件
"./src/**/*.d.ts"
]
}
声明文件使用declare
关键字来声明文件;
查看声明文件
在ts
中,大多数库都被社区编写了声明文件,在node_modules
找到安装的库,之后查看*.d.ts
文件,里面就是写好的声明文件,如果没有,则需要手动安装,安装时加上@types/*
即可,如果安装成功了,说明有这个库的声明文件,如果找不到安装的模块,则需要手动编写声明文件;
全局库
如何判断是否是全局可以使用的变量:
官方声明文件的例子:官方模块,可以参考global.d.ts
文件的例子;
通过定义document
或者window
上面添加方法时,都是全局可以使用的变量
// 如果添加了一个全局的getTitle方法,并且返回的是string, 当声明了之后则可以使用了;
declare function getTitle(): string
当修改了声明文件时,需要重新编译,否则报错;
模块化库
使用import
语句或者require
语句的,一般都是模块化库
可以参数官方的module-*.d.ts
的模板;
UMD库
UMD模块是指那些既可以作为模块使用(通过导入)又可以作为全局(在没有模块加载器的环境里)使用的模块。
识别UMD模块
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(["libName"], factory);
} else if (typeof module === "object" && module.exports) {
module.exports = factory(require("libName"));
} else {
root.returnExports = factory(root.libName);
}
}(this, function (b) {
很多库都是UMD
库,比如jquery
、moment
修改全局模块编写声明文件
一个全局插件是全局代码,它们会改变全局对象的结构。 对于 全局修改的模块,在运行时存在冲突的可能。
当我们在String
、Array
等原型上面添加了方法时,如何填写声明文件
String.prototype.getFirstLetter = function(){
return this[0]
}
// global.d.ts 写声明文件
// 利用声明合并
interface String {
getFirstLetter(): string
}
使用依赖
依赖全局库
如果库依赖了某个全局库,使用reference
指定types
来引入该模块
/// <reference types='moment'/>
依赖模块
使用import
语句
import * as moment from "moment";
依赖UMD库
如果你的全局库依赖于某个UMD模块,使用
/// <reference types
指令:ts/// <reference types="moment" /> function getThing(): moment;
如果你的模块或UMD库依赖于一个UMD库,使用
import
语句:tsimport * as someLib from 'someLib';
不要使用
///reference
引入
注意:
- 防止命名冲突,因为都是在全局填写的,很容易产生冲突,建议将相关的东西放在命名空间里面,使用对象的形式去访问,防止命名污染
- 一些插件添加或修改已存在的顶层模块的导出部分。 当然这在CommonJS和其它加载器里是允许的,ES模块被当作是不可改变的因此这种模式就不可行了。 因为TypeScript是能不预知加载器类型的,所以没没在编译时保证,但是开发者如果要转到ES6模块加载器上应该注意这一点。
快捷外部模块声明
如果使用一个新模块,不想花时间精力为该模块填写声明,只需要在typing
文件夹下面创建文件夹编写即可,比如moment
:
// typings/moment/index.d.ts
declare module 'moment' //快速导出模块
模块解析
以下内容进行了解就可以了
模块解析分为两种:node
解析和classic
解析,通过tsconfig.json
文件的moduleResolution
设置,如果不设置默认为classic
解析方式;
classic
解析策略:
- 当省略
ts
文件时首先会查看.ts
文件,如果找不到则查找.d.ts
文件,还是找不到则向上一级去查找,继续按照前面两种文件类型查找;
node
解析策略:
- 模拟
nodejs
模板解析策略,在编译阶段定位模块文件的,首先找.ts
文件,之后找.tsx
文件,之后找.d.ts
三种文件;
nodejs
会查找package.json
里面的main
确定入口文件,而ts
会首先查找types
确定入口文件,之后再查找main
入口文件
模块解析配置项
通过配置项,来确定模块的导入,配置项在tsconfig.json文件
baseUrl
:用来设置编译之后文件都放在哪个文件夹下;paths
: 用来设置路径映射,paths
是相对于baseUrl
的,指定paths
就必须指定baseUrl
,常用于配置第三方模块的引入,经常在node_modules/@types
和src/typings
文件夹查找,设置:json{ "baseUrl": "./", // 如果是当前根目录,就填写一个.即可 "paths": { "*": ["node_modules/@types", "src/typings"] } }
rootDirs
:路径列表,在编译时,编译器会将这个路径列表中的内容放到一个文件夹中,当modules
文件夹中的index.ts
要引入ts-modules
文件夹里面的a.ts
文件,设置了路径列表之后,只需要写相对路径即可ts{ "rootDirs": ["src/modules", "src/ts-modules"] }