本文讲述了如何将 JavaScript 项目迁移到 TypeScript 上,以及如何在项目中添加 TypeScript 配置,编写 TypeScript 代码。

一、插件安装

安装项目所需插件,一般对应的模块都会有对应的 @types 插件可以使用。不知道的是否需要安装对应的 @types 插件的话,可以到 TypeSearch 进行查找。

1
2
3
4
5
6
7
8
# 安装项目中使用的插件
$ npm install typescript ts-jest ts-loader @types/enzyme @types/jest @types/node @types/react @types/react-dom --save-dev

# 安装 tslint 相关插件
$ npm install tslint tslint-config-prettier tslint-react --save

# 安装 webpack 中对 typescript 支持的插件
$ npm install fork-ts-checker-webpack-plugin tsconfig-paths-webpack-plugin --save-dev

二、添加 tsconfig.json 配置文件

在项目根目录下添加 tsconfig.json 配置文件。tsconfig.json文件中指定了用来编译这个项目的根文件和编译选项。

tsconfig.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
"compilerOptions": {
"baseUrl": ".",
"outDir": "build/dist",
"module": "commonjs",
"target": "es5",
"lib": ["es6", "dom"],
"sourceMap": true,
"allowJs": true,
"jsx": "react",
"moduleResolution": "node",
"rootDir": "src",
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"experimentalDecorators": true
},
"exclude": [
"config",
"public",
"node_modules",
"build",
"dist",
"scripts",
"acceptance-tests",
"webpack",
"jest",
"src/setupTests.ts",
"jest.config.js"
],
"types": [
"typePatches"
]
}

再添加一个 tsconfig.prod.json 文件,用来在项目生产环境配置中使用。

tsconfig.prod.json

1
2
3
{
"extends": "./tsconfig.json"
}

这里直接继承类 tsconfig.json 文件中的内容。也可以添加一些不同的配置。


三、为项目添加 TsLint 配置文件

在项目根目录下添加 tslint.json 文件。tslint.json 中配置了开发过程中的规则。

tslint.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
"defaultSeverity": "warning",
"rules": {
// 对象属性是否按照顺序进行编写
"object-literal-sort-keys": false,
// jsx 中是否允许使用 lambda 语法
"jsx-no-lambda": false,
// 引入模块是否需要按照字母顺序
"ordered-imports": false,
// 不允许打印 console
"no-console": false,
// 不允许隐式的依赖模块,比如引用别名中的模块
"no-implicit-dependencies": false,
// 是否必须使用 === 取代 ==
"triple-equals": false,
// 对象成员是否需要按照顺序进行编写
"member-ordering": false
},
"linterOptions": {
"exclude": [
"config/**/*.js",
"webpack/**/*.js",
"node_modules/**/*.ts",
"coverage/lcov-report/*.js",
"src/**/*.js",
"src/**/*.jsx"
]
}
}

  • extends:继承了哪些规则
  • defaultSeverityTsLint 严重性等级,可以是 warning 或是 error
  • rules:配置规则,可以修改一些默认的 TsLint 规则
  • linterOptions.exclude:排除掉不需要进行 TsLint 检查的文件
  • 更多 TsLint 的规则配置可以参考 TsLint

四、在 webpack 配置文件中添加 TypeScript 配置

在 webpack 开发环境中添加配置

使用插件

在 webpack 配置文件中使用插件:

  • 在 plugins 中使用 ForkTsCheckerWebpackPlugin 插件
  • 注意: 在 resolve.plugin 中使用 TsconfigPathsPlugin 插件

webpack.config.dev.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
...

module.exports = {
...

plugins: [
new ForkTsCheckerWebpackPlugin({
async: false,
watch: path.resolve(__dirname, '../src'),
tsconfig: path.resolve(__dirname, '../tsconfig.json'),
tslint: path.resolve(__dirname, '../tslint.json')
})
],
resolve: {
...

plugins: [
new TsconfigPathsPlugin({ configFile: path.resolve(__dirname, '../tsconfig.json') })
],
...
}
}

在 webpack 中添加 TypeScript 的 rules 配置

使用 ts-loader

webpack.config.dev.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...

module.exports = {
...
rules: [
{
test: /\.(ts|tsx)$/,
include: path.resolve(__dirname, '../src'),
use: [
{
loader: require.resolve('ts-loader'),
options: {
// disable type checker - we will use it in fork plugin
transpileOnly: true
}
}
]
},
...
],
...
}

在 webpack 生产环境中添加配置

使用方式和上面 在 webpack 开发环境中添加配置 的方式一致。唯一不同的就是在使用插件的时候,将 tsconfig.json 修改为 tsconfig.prod.json

webpack.prod.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module.exports = {
...

plugins: [
new ForkTsCheckerWebpackPlugin({
async: false,
watch: path.resolve(__dirname, '../src'),
tsconfig: path.resolve(__dirname, '../tsconfig.prod.json'),
tslint: path.resolve(__dirname, '../tslint.json')
})
],
resolve: {
...

plugins: [
new TsconfigPathsPlugin({ configFile: path.resolve(__dirname, '../tsconfig.prod.json') })
],
...
}
}

五、遇到的问题

装饰器使用问题

本来配置好的装饰器,使用的好好的,配置完 TypeScript 之后,却发现编辑器对应文件里面报红线错误提示:

1
Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning.

解决办法:在根目录下的 tsconfig.json 文件里面添加对应配置即可

tsconfig.json

1
2
3
4
5
{
"compilerOptions": {
"experimentalDecorators": true
}
}

生命周期提示红线报错问题

使用函数方式创建组件没有问题,使用类的方式创建时,生命周期函数下面都会报红线提示错误:Parsing error: Unexpected token

解决办法:将 VSCode 设置中的配置项进行修改即可

1
2
3
4
5
6
7
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
// 下面这个对使用 ts 编写的 React 组件进行 ESLint 的文件检查暂时先去掉
// "typescriptreact"
]

tsconfig.json 文件内部报错问题

tsconfig.json 文件内部报错,第一行大括号那里就出现错误,错误提示类似下面这种:

1
2
3
'c:/xxx/config/dev.js' is not under 'rootDir' 'c:/xxx/src'. 'rootDir' is expected to contain all source files."

JSON schema for the TypeScript compiler's configuration file

这里我 tsconfig.json 文件中我配置的 rootDirsrc 目录,但是在 exclude 属性里,我没有将 src 的同级目录 config 给排除,所以就会提示这个错误,在 tsconfig.json 中添加配置即可:

tsconfig.json

1
2
3
4
5
6
{
"exclude": [
...
"config"
],
}

出现类似的问题,提示哪个目录不在 rootDir 目录下,就将哪个目录添加到 exclude 属性里。

webpack 中配置的别名,在 ts 文件中不识别的问题

在 webpack 中为部分目录配置了别名,可以直接目录,会自动到对应目录下寻找模块,在 js 文件中可以正常使用,但是在 ts 文件中却会报错:Cannot find module 'utils/xxx'

解决办法:这时需要在 tsconfig.json文件中单独配置 paths 列表,对对应的路径进行映射:

tsconfig.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"src/*": [
"src/*"
],
"utils/*": [
"src/utils/*"
]
}
},
...
}

这样启动项目就不会再报错,但是在 ts 文件里还是会有红线报错提醒,此时还需要在 tslint.json 文件中添加 rules 配置:

tslint.json

1
2
3
4
5
6
7
{
...
"rules": {
"no-implicit-dependencies": false
}
...
}

TsconfigPathsPlugin 插件位置配置错误问题

TsconfigPathsPlugin 插件要配置在webpack 配置文件中 resolve 属性下的 plugins 里,否则的话会有问题。比如,直接放在了 webpack 配置文件中的 plugins 中就可能会出现两个问题:

    1. 如果 tsconfig.json 文件中 compilerOptions 属性下没有配置 baseUrl 属性,就会提示 Found no baseUrl in tsconfig.json, not applying tsconfig-paths-webpack-plugin
    1. 然后配置 baseUrl 属性 ,配置好之后还可能会报错:`tsconfig-paths-webpack-plugin: No file system found on resolver. Please make sure you’ve placed the plugin in the correct part of the configuration. This plugin is a resolver plugin and should be placed in the resolve part of the Webpack configuration.

注意:所以 tsconfig-paths-webpack-plugin 插件的位置一定要放在 webpack 配置文件中 resolve 属性下的 plugins 里。

写在后面

这就是目前在项目中添加的部分 TypeScript 以及 TsLint 配置。此时已经可以在项目中正常编写 TypeScript 代码了。

如果大家在项目迁移的过程中如果遇到了别的问题,也可以拿出来交流探讨一下。