1. 共存策略:在既有项目中使用TS

共存策略,即既有的React项目是基于JS/JSX编写的,在新的模块中采用TS/TSX的方式编写。

我们分别以 .ts.tsx 文件举例,看需要做哪些配置,让项目支持TypeScript。

1.1 支持 .ts 文件

定义好下述.ts文件,并且在我们的代码中引用:

src/component/demo/add.ts

  1. export default function(a:number, b: number) {
  2. return a + b;
  3. }

src/App.js

  1. import add from './components/demo/add';
  2. console.log('1+2=' + add(1,2));

首先,需要安装typescriptts-loader:

  1. $ npm i typescript ts-loader -D

然后,提供编译选项,通过如下命令生成默认的配置即可,它会在项目根目录下生成 tsconfig.js

  1. $ node_modules/.bin/tsc --init

最后,需要在webpack的配置中增加对 .ts.tsx 文件的识别,并且正确处理它们:

webpack.base.js

  1. module.exports = {
  2. module: {
  3. rules: [{
  4. test: /\.tsx?$/, use: ['babel-loader', 'ts-loader']
  5. }]
  6. },
  7. resolve: {
  8. extensions: ['.js', '.ts', '.tsx'],
  9. },
  10. };

启动项目可以看到控制台正确输出1+2=3

1.2 支持 .tsx 文件

简单定义了一个 Hello.tsx,声明了 props 的结构,在render中展示传入的msg

src/components/demo/Hello.tsx

  1. import React, { Component } from 'react';
  2. interface Props {
  3. msg: string
  4. }
  5. class Hello extends Component<Props> {
  6. render() {
  7. return <div>{this.props.msg}</div>
  8. }
  9. }
  10. export default Hello;

src/App.js

  1. import Hello from './components/demo/Hello';
  2. render() {
  3. //省略无关代码
  4. <Hello msg="hello typescript"></Hello>
  5. }

安装它们的声明文件后,即可在 tsx 正常使用React:

  1. $ npm i @types/react @types/react-dom -D

启动项目可以看到界面展示我们输出的 hello typescript

1.3 检查js文件

打开 tsconfig.js 中的如下参数,可以让编译过程也检查 .js 文件,同时排除掉 node_modules 目录:

🤔 下述配置并没有生效,node_modules 下的文件仍被 TS 编译命中抛出了错误。

tsconfig.js

  1. {
  2. "include": [
  3. "src/**/*"
  4. ],
  5. "exclude": [
  6. "node_modules",
  7. "**/*.spec.ts"
  8. ],
  9. "compilerOptions": {
  10. "allowJs": true, /* Allow javascript files to be compiled. */
  11. "checkJs": true, /* Report errors in .js files. */
  12. }
  13. }

可以看到输出了大量的compile error,但并不影响使用。为了在 .js 中跳过这样的检查,可以通过在 js 文件的行首增加 // @ts-nocheck 或 doc注释:

src/components/demo/add.ts

  1. // @ts-nocheck
  2. export default function(a, b) {
  3. return a+b;
  4. }


src/components/demo/add.ts

  1. /**
  2. * @param {number} a
  3. * @param {string} b
  4. */
  5. export default function(a, b) {
  6. return a+b;
  7. }

2. 宽松策略:所有文件改为JS/JSX

前述在新模块中使用了 .ts.tsx,这里介绍如何重命名为已有的 .js.jsx文件,并且项目可运行。

首先,安装需要用到的 shelljsts-node

  1. $ npm i -D shelljs ts-node

借助于 shelljs 整个工具,我们将所有在 src 下的文件后缀进行重命名:

renameJS.ts

  1. import * as shellJs from 'shelljs';
  2. shellJs.find('src')
  3. .filter(file => file.match(/jsx?$/))
  4. .forEach(file => {
  5. let newFile = file.replace(/j(sx?)/, 't$1')
  6. shellJs.mv(file, newFile);
  7. })

pacakge.json 中增加配置用于执行它

pacakge.json

  1. {
  2. "scripts": {
  3. "rename-js": "ts-node renameJs.ts"
  4. }
  5. }

在命令行中执行 npm run rename-js后可以查看到 .js.jsx 后缀被替换为了 .ts.tsx
仍旧有几个点需要进行确认:

  1. 在React中 .js.jsx 中都可以书写JSX,重命名后,需要确保后用到了JSX的文件都以 .tsx 结尾。
  2. 自己书写的Webpack文件,入口文件都要从 .js 文件改为 .ts文件。
  3. 已有都项目如果使用到了 react-router-domreduxreact-redux,需要安装对应的 @types/*
  4. 为了让编译错误少一些,我们可以将 tsconfig.js 中跟 strict 相关的配置项注释掉,从而减少编译报错。

    3. 严格模式:逐步排除不严格的代码书写

在宽松模式下开发一段时间,仍旧有精力可以逐步将旧有的代码逐步进行重构的时候,我们可以打开 tsconfig.js 中的 Strict Type-Checking OptionsAdditional Checks部分。基于各种编译报错,我们可以进一步修改代码,让代码具备更严格的类型约束。