JavaScript 项目迁移到 TypeScript 步骤以及遇到的问题

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

1、插件安装

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

# 安装项目中使用的插件
$ 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
复制代码

2、添加 tsconfig.json 配置文件

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

tsconfig.jsonreact

{
  "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 文件,用来在项目生产环境配置中使用。webpack

tsconfig.prod.jsongit

{
  "extends": "./tsconfig.json"
}
复制代码

这里直接继承类 tsconfig.json 文件中的内容。也能够添加一些不一样的配置。es6


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

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

tslint.jsonweb

{
  "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

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

在 webpack 开发环境中添加配置

使用插件

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

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

webpack.config.dev.js

...
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

...

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

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') })
        ],
        ...
    }
}
复制代码

5、遇到的问题

装饰器使用问题

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

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

{
    "compilerOptions": {
        "experimentalDecorators": true
    }
}
复制代码

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

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

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

"eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    // 下面这个对使用 ts 编写的 React 组件进行 ESLint 的文件检查暂时先去掉  
    // "typescriptreact"	
]
复制代码

tsconfig.json 文件内部报错问题

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

'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

{
  "exclude": [
    ...
    "config"
  ],
}
复制代码

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

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

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

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

tsconfig.json

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "src/*": [
            "src/*"
          ],
          "utils/*": [
            "src/utils/*"
          ]
        }
	  },
    ...
}
复制代码

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

tslint.json

{
    ...
    "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 代码了。

若是你们在项目迁移的过程当中若是遇到了别的问题,也能够拿出来交流探讨一下。