1. 共存策略:在既有项目中使用TS
共存策略,即既有的React项目是基于JS/JSX编写的,在新的模块中采用TS/TSX的方式编写。
我们分别以 .ts
和 .tsx
文件举例,看需要做哪些配置,让项目支持TypeScript。
1.1 支持 .ts
文件
定义好下述.ts
文件,并且在我们的代码中引用:
src/component/demo/add.ts
export default function(a:number, b: number) {
return a + b;
}
src/App.js
import add from './components/demo/add';
console.log('1+2=' + add(1,2));
首先,需要安装typescript
和 ts-loader
:
$ npm i typescript ts-loader -D
然后,提供编译选项,通过如下命令生成默认的配置即可,它会在项目根目录下生成 tsconfig.js
:
$ node_modules/.bin/tsc --init
最后,需要在webpack的配置中增加对 .ts
和 .tsx
文件的识别,并且正确处理它们:
webpack.base.js
module.exports = {
module: {
rules: [{
test: /\.tsx?$/, use: ['babel-loader', 'ts-loader']
}]
},
resolve: {
extensions: ['.js', '.ts', '.tsx'],
},
};
1.2 支持 .tsx
文件
简单定义了一个 Hello.tsx
,声明了 props
的结构,在render
中展示传入的msg
:
src/components/demo/Hello.tsx
import React, { Component } from 'react';
interface Props {
msg: string
}
class Hello extends Component<Props> {
render() {
return <div>{this.props.msg}</div>
}
}
export default Hello;
src/App.js
import Hello from './components/demo/Hello';
render() {
//省略无关代码
<Hello msg="hello typescript"></Hello>
}
安装它们的声明文件后,即可在 tsx
正常使用React:
$ npm i @types/react @types/react-dom -D
启动项目可以看到界面展示我们输出的 hello typescript
。
1.3 检查js文件
打开 tsconfig.js
中的如下参数,可以让编译过程也检查 .js
文件,同时排除掉 node_modules
目录:
🤔 下述配置并没有生效,node_modules
下的文件仍被 TS 编译命中抛出了错误。
tsconfig.js
{
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
],
"compilerOptions": {
"allowJs": true, /* Allow javascript files to be compiled. */
"checkJs": true, /* Report errors in .js files. */
}
}
可以看到输出了大量的compile error,但并不影响使用。为了在 .js
中跳过这样的检查,可以通过在 js 文件的行首增加 // @ts-nocheck
或 doc注释:
src/components/demo/add.ts
// @ts-nocheck
export default function(a, b) {
return a+b;
}
src/components/demo/add.ts
/**
* @param {number} a
* @param {string} b
*/
export default function(a, b) {
return a+b;
}
2. 宽松策略:所有文件改为JS/JSX
前述在新模块中使用了 .ts
和 .tsx
,这里介绍如何重命名为已有的 .js
和 .jsx
文件,并且项目可运行。
首先,安装需要用到的 shelljs
和 ts-node
$ npm i -D shelljs ts-node
借助于 shelljs
整个工具,我们将所有在 src
下的文件后缀进行重命名:
renameJS.ts
import * as shellJs from 'shelljs';
shellJs.find('src')
.filter(file => file.match(/jsx?$/))
.forEach(file => {
let newFile = file.replace(/j(sx?)/, 't$1')
shellJs.mv(file, newFile);
})
在 pacakge.json
中增加配置用于执行它
pacakge.json
{
"scripts": {
"rename-js": "ts-node renameJs.ts"
}
}
在命令行中执行 npm run rename-js
后可以查看到 .js
和 .jsx
后缀被替换为了 .ts
和 .tsx
。
仍旧有几个点需要进行确认:
- 在React中
.js
和.jsx
中都可以书写JSX,重命名后,需要确保后用到了JSX的文件都以.tsx
结尾。 - 自己书写的Webpack文件,入口文件都要从
.js
文件改为.ts
文件。 - 已有都项目如果使用到了
react-router-dom
,redux
,react-redux
,需要安装对应的@types/*
- 为了让编译错误少一些,我们可以将
tsconfig.js
中跟 strict 相关的配置项注释掉,从而减少编译报错。3. 严格模式:逐步排除不严格的代码书写
在宽松模式下开发一段时间,仍旧有精力可以逐步将旧有的代码逐步进行重构的时候,我们可以打开 tsconfig.js
中的 Strict Type-Checking Options
和 Additional Checks
部分。基于各种编译报错,我们可以进一步修改代码,让代码具备更严格的类型约束。