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-nocheckexport 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部分。基于各种编译报错,我们可以进一步修改代码,让代码具备更严格的类型约束。
