前言
本篇主要介绍:
- Typescript文件的编译处理。
- TypeScript 中的 tsconfig.json 文件的作用、配置参数。
如果一个目录下存在一个 tsconfig.json 文件,那么它意味着这个目录是 TypeScript 项目的根目录。tsconfig.json 文件中指定了用来编译这个项目的根文件和编译选项。 一个项目可以通过以下方式之一来编译:
- 不带任何输入文件的情况下调用
tsc,编译器会从当前目录开始去查找tsconfig.json文件,逐级向上搜索父目录。 - 不带任何输入文件的情况下调用
tsc,且使用命令行参数--project(或-p)指定一个包含tsconfig.json文件的目录。
当命令行上指定了输入文件时,tsconfig.json文件会被忽略。
一、TS执行编译
手动编译
指定tsconfig.json
不指定tsconfig.json的情况,会自动获取当前项目根路径下的配置文件。找不到的情况会逐级向上查找。
指定编译配置文件 tsc -p
Typescript使用.ts作为扩展名,想要运行这段代码,需要先编译ts文件中的代码。
tsc greeter.ts
编译后输出一个greeter.js文件,此时就可以执行该段代码了。
自动编译
tsc -w
自动编译存在的问题,增加修改ts文件都会对应输出到编译后指定的文件中,但是,当删除一个ts文件时,并不会上出掉该文件之前已经编译好的对应的js文件,说白了,是“覆盖”。
其他执行指令
TSC 的可选项:
- –project(简写 -p):编译器直接在该目录下查找 tsconfig.json 文件,如果没找到则报错。
- –build(简写 -b):编译器会进行增量构建。先找到所有引用的工程,然后检查它们是否为最新版本,最后按顺序构建非最新版本的工程。
- –verbose(简写 -v):打印详细的日志(可以与其它标记一起使用)。
- –dry: 显示将要执行的操作但是并不真正进行这些操作。
- –clean: 删除指定工程的输出(可以与–dry一起使用)。
- –force: 把所有工程当作非最新版本对待。
- –watch(简写 -w):观察模式。watch 模式监控当前项目 ts 文件变化立即进行编译。
自动编译并执行ts文件
ts-node xxx.ts
现成的依赖,帮我们编译并执行ts文件
二、配置参数
声明文件@types/
当我们直接在项目中引入第三方的模块,并且使用其方法或者是属性,ts 是不会报错的,因为这些类型和方法都是没有进行声明的。因为我们需要使用声明文件来定义这些属性和方法的类型。对于一些常用的第三方模块, typescript 社区已经帮我们定义好了,只要我们在使用 npm 安装模块的时候,在模块名前带上 @types/
npm install express --save// 安装普通的 express 模块
npm install @types/express --save-dev// 安装带有声明文件的 express 模块,只有本地开发环境才进行安装
Common
1. compilerOptions
- rootDir
用来指定编译文件的根目录,编译器会在根目录查找入口文件。 "rootDir": "./",
- outDir
指定输出目录
"outFile": "./"
- rootDirs
可以指定一个路径列表,在构建时编译器会将这个路径中的内容都放到一个文件夹中,通常不配置,用于运行时 "rootDirs": [],
比如 我们创建以下两个文件。
// /util/a.ts
let a: string = 'A'
export = a
// /src/index.ts
import a from './a'
注意在引入 a 时,是引入的当前目录。因为当 rootDirs 设置了 src 和 util 目录时,编译器默认它们属于同级目录。
- outFile
将多个相互依赖的文件生成一个文件,(文件合并的书序位加载和依赖的顺序)可以用在module为 AMD & System时。
"outFile": "./app.js"
- baseUrl
设置baseUrl来告诉编译器到哪里去查找模块。所有非相对模块导入都会被当做相对于 baseUrl。有点类似alias。
"baseUrl": "./src",
原本,一个子文件下引入utils中的工具,引入模块的路径
../../../static,配置之后,可以从相对路径引入utils/static
- paths
模块名到基于 baseUrl的路径映射的列表,是相对于"baseUrl"进行解析。那有的同学有疑问了,vite.resolve.alia不是配置过么? 解释一下,这里配置的paths是为了让ts编译时能够解析对路径。
"paths": {
"@/*": ["src/*"],
"views/*": ["src/views/*"],
"components/*": ["src/components/*"],
"assets/*": ["src/assets/*"],
"*": ["src/*"]
}
- types
声明文件包,添加要包含的类型声明文件名列表,只有在这里列出的模块的声明文件才会被加载进来。这个也是要关注到的哈,省得一堆波浪线。 如果设置了某一个声明文件,那么编译器只会加载这个声明文件。
- typeRoots
用来指定声明文件或文件夹的路径列表,如果指定了此项,则只有在这里列出的声明文件才会被加载,通常不配置。声明文件目录,默认 node_modules/@types "typeRoots": [],
- declarationDir
声明文件的生成的路径 "declarationDir": "./d"
非路径配置输入
- target
用来指定最终代码运行环境所支持的 JavaScrpt 语法的版本是什么。 "ES5", "ES6"/ "ES2015", "ES2016", "ES2017"或 "ESNext"。 vue3+Vite的技术栈项目中,记得调整为esnext。 默认位ES3
"target": "esnext"
- module
用来指定编译后模块化代码规范。"None", "CommonJS", "AMD", "System", "UMD", "ES6"或 "ES2015"。只有 "AMD"和 "System"能和 --outFile一起使用。"ES6"和 "ES2015"可使用在目标输出为 "ES5"或更低的情况下。
"module": "UMD"
- moduleResolution
选择模块解析策略,有“node”和“classic”两种。如果未指定,则 --module commonjs 默认为 Node,否则默认为 Classic(包括 --module 设置为 amd、system、umd、es2015、esnext 等时)。注意:Node 模块解析是 TypeScript 社区中最常用的,推荐用于大多数项目。 如果您在 TypeScript 中遇到导入和导出的解析问题,请尝试设置 moduleResolution: “node” 以查看它是否解决了问题。 "moduleResolution": "node",
- lib
编译器选项,TS 包含在编译中的库文件,es5 默认 "dom", "es5", "scripthost",例如,我们想在
ts中使用 es2019 的方法。可以在lib配置里添加es2019。
"lib": ["esnext", "dom"],
- jsx
指定jsx代码用于的开发环境,有“preserve”, "react-native", "react" "jsx": "preserve",
preserve:生成代码中会保留JSX以供后续的转换操作使用(比如:Babel).另外,输出文件会带有.jsx扩展名。
react:会生成React.createElement,在使用前不需要再进行转换操作了,输出文件的扩展名为.js。
react-native:相当于preserve,它也保留了所有的JSX,但是输出文件的扩展名是.js
模式 输入 输出 输出文件扩展名
preserve <div /> <div /> .jsx
react <div /> React.createElement("div") .js
react-native <div /> <div /> .js
- isolatedModules
将导入或者导出的每个文件作为单独的模块。默认为false
- esModuleInterop
允许 export = 导出,由import = 导入
- noEmit
不生产编译文件
- noEmitOnError
发生错误时不输出文件
- skipLibCheck
忽略所有的声明文件( *.d.ts)的类型检查。这个属性不但可以忽略 npm 不规范带来的报错,还能最大限度的支持类型系统。设置为 true 就不用怕使用的第三方库不规范了。这也算一个难受的点吧,毕竟不是所有的SDK都是规范的ts支持。
- declaration
用来指定是否在编译的时候生成相的d.ts声明文件,如果设为true,编译每个ts文件之后会生成一个js文件和一个声明文件,但是declaration和allowJs不能同时设为true
- emitDeclarationOnly
只生成声明文件
- declarationMap
用来指定编译时是否生成declaration声明文件的.map文件
- sourceMap
用来指定编译时是否生成目标文件的.map文件 "sourceMap": true,
- inlineSourceMap
inlineSourceMap指定是否将map文件内容和js文件编译在一个同一个js文件中,如果设为true,则map的内容会以//#soureMappingURL=开头,然后接base64字符串的形式插入在js文件底部 "inlineSourceMap": true,
- inlineSources
inlineSources用于指定是否进一步将ts文件的内容也包含到输出文件中 "inlineSources": true,
- sourceRoot
sourceRoot用于指定调试器应该找到TypeScript文件而不是源文件的位置,这个值会被写进.map文件里 "sourceRoot": "",
- mapRoot
mapRoot用于指定调试器找到映射文件而非生成文件的位置,指定map文件的根路径,该选项会影响.map文件中的sources属性 "mapRoot": "",
- removeComments
终于指定是否删除编译后文件中的注视
- allowJs
用来指定是否允许编译JS文件,默认false,即不编译JS文件
- checkJs
用来指定是否检查和报告JS文件中的错误,默认false
编译语法项
- strict
用于指定是否启动所有类型检查,如果设为true这回同时开启下面这几个严格检查,默认为false。若
strict为 true,alwaysStrict、noImplicitAny、strictNullChecks、strictFunctionTypes、strictPropertyInitialization、strictBindCallApply和noImplicitThis选项默认都为 true。
- alwaysStrict
指定始终以严格模式检查每个模块,并且在编译之后的JS文件中加入"use strict"字符串,用来告诉浏览器该JS为严格模式
- noImplicitAny
如果我们没有一些值设置明确类型,编译器会默认认为这个值为any类型,如果将noImplicitAny设为true,则如果没有设置明确的类型会报错,默认值为false,这个从个人经验分析,还是不打开为好。
- strictNullChecks
当设为true时,不允许把
null、undefined赋值给其他类型变量。除了any类型,还有个例外就是undefined可以赋值给void类型
- strictFunctionTypes
用来指定是否使用函数参数双向协变检查
- strictBindCallApply
设为true后对bind、call和apply绑定的方法的参数的检测是严格检测
function add (a: number, b: number) { return a + b }
add.call(undefined, 1, '2')
// Error: Argument of type '"2"' is not assignable to parameter of type 'number'.
- strictPropertyInitialization
设为true后会检查类的非undefined属性是否已经在构造函数里初始化,如果要开启这项,需要同时开启strictNullChecks,默认为false
- noImplicitThis
不允许
this有隐式的any类型。
class A {
name: string = 'abc'
getName () {
return function () {
console.log(this.name)
}
}
}
// Error: 'this' implicitly has type 'any' because it does not have a type annotation.
- noUnusedLocals
用于检查是否有定义了但是没有使用变量,对于这一点的检测,使用ESLint可以在你书写代码的时候做提示,你可以配合使用,他的默认值为false
- noUnusedParameters
用于检测是否在函数中没有使用的参数
- noImplicitReturns
用于检查函数是否有返回值,设为true后,如果函数没有返回值则会提示,默认为false
- noFallthroughCasesInSwitch
用于检查switch中是否有case没有使用break跳出switch,默认为false
- allowSyntheticDefaultImports
用来指定允许从没有默认导出的模块中默认导入
- experimentalDecorators
experimentalDecorators用于指定是否启用实验性的装饰器特性
- emitDecoratorMetadata
用于指定是否为装上去提供元数据支持,关于元数据,也是ES6的新标准,可以通过Reflect提供的静态方法获取元数据,如果需要使用Reflect的一些方法,需要引用ES2015.Reflect这个库
2. files
编译器需要编译的相对或绝对文件路径的单个文件列表, 这时执行
tsc命令,编译器会编译src/index.ts文件。 "files": [ "src/index.ts" ]
3. include
指定要编译的路径列表, 编译器会编译 指定 目录下的所有
ts文件。 如果files和includes都没有指定,编译器默认包含当前目录下所有的ts文件。 "include":[],
4. exclude
不编译的文件,它也可以指定一个列表,规则和include一样,可以是文件可以是文件夹,可以是相对路径或绝对路径,可以使用通配符' "exclude":[],
5. extends
可以通过指定一个其他的tsconfig.json文件路径,来继承这个配置文件里的配置,继承来的文件的配置会覆盖当前文件定义的配置 "extends":""
6. compileOnSave
设为true,在我们编辑了项目文件保存的时候,编辑器会根据tsconfig.json的配置更新重新生成文本,不过这个编辑器支持
7. references
指定要引用的项目。references属性是 TypeScript 3.0 的新特性,允许将 TypeScript 程序拆分结构化。有点类似组件的思路,避免一个配置文件过于繁琐。分别配置不同的部分,达到更加清晰。 "references": [{ "path": "./tsconfig.node.json" }]
React
Vue
Vue3 + Vite 项目基础配置
# tsconfig.json
{
"compilerOptions": {
"baseUrl": "./",
"skipLibCheck": true,
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"noImplicitAny": false,
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"types": ["vite/client"],
"isolatedModules": true,
"paths": {
"@/*": ["src/*"],
"views/*": ["src/views/*"],
"components/*": ["src/components/*"],
"assets/*": ["src/assets/*"],
"*": ["src/*"]
}
},
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue"
],
"exclude": ["node_modules", "dist"]
}