学习了 TypeScript
,肯定是跃跃一试、小试牛刀,想找个已有 JavaScript
项目改造一下。
首先做一下心理按摩:对已有项目进行迁移将是一个渐进过程,不会一气呵成。
项目的迁移有三个主流策略:
- 共存策略
- 宽松策略
- 严格策略
我们以一个 react
项目做例子,三个策略的前两步是一样的:
安装
安装 typescript 和 react 声明文件
$ npm i typescript @types/react @types/react-dom
复制代码
初始化 tsconfig.json
$ tsc --init
复制代码
- tsconfig.json
{ "jsx": "react" } 复制代码
共存策略
所谓共存策略:原来的
JS
代码不做修改,新增的代码用TS
编写。
babel-loader? ts-loader?
如果你的构建工具深度依赖 babel
,则可以选择使用 babel-loader
做语言转换、tsc
做类型检查;否则可以选择更轻量的 ts-loader
。
鉴于目前大多数的 React
项目都使用了 babel
,我们先看选择 babel
的处理方式
babel-loader
-
安装
@babel/preset-typescript
$ npm i -D @babel/preset-typescript 复制代码
-
修改 babel 配置
{ "presets": [ "@babel/env", "@babel/preset-react", + "@babel/preset-typescript" ], "plugins": [ "@babel/proposal-class-properties", "@babel/proposal-object-rest-spread" ] } 复制代码
-
修改 webpack.base.config.js
module.exports = { // ... resolve: { extensions: [".js", ".jsx", ".ts", ".tsx"], }, module: { rules: [ { test: /\.(j|t)sx?$/, use: [ { loader: "babel-loader", }, ], exclude: /node_modules/, }, ], }, }; 复制代码
-
添加类型检查
-
tsconfig.json
{ "compilerOptions": { "noEmit": true } } 复制代码
-
package.json:添加类型检查脚本
{ // ... "scripts": { // ... "type-check": "tsc --watch" } } 复制代码
-
-
ts-loader
ts-loader
的处理方式会更简单
-
安装
ts-loader
npm i ts-loader -D 复制代码
-
修改 webpack.base.config.js
module.exports = { // ... resolve: { extensions: [".js", ".jsx", ".ts", ".tsx"], }, module: { rules: [ // ... { test: /\.tsx?$/, use: [ { loader: "ts-loader", }, ], exclude: /node_modules/, }, ], }, }; 复制代码
js、jsx 也不能放过
-
tsconfig.json
** 所有子目录。包括子目录的子目录。 * 只是一级子目录
{ "include": ["./src/**/*"], "compilerOptions": { // ... "allowJs": true, "checkJs": true } } 复制代码
类型检查的报错,并不影响构建。
在不修改 JS
代码的前提下,有两种处理报错的方式:
-
@ts-nocheck
// @ts-nocheck export function add(x, y) { return x + y; } 复制代码
-
JSDoc
这种方法在写代码时,也会进行类型检查
/** * @param {number} x * @param {number} y */ export function add(x, y) { return x + y; } 复制代码
宽松策略
所谓宽松策略:将所有的
js
/jsx
,重命名为ts
/tsx
。并且在不修改代码的基础上,使用最宽松的检查规则,忽略剩余的报错,使工程跑起来。
重命名
我们借助 shelljs
来完成重命名工作,先安装一下 shelljs
;
node
命令默认寻找 js
文件,所以我们还需要安装 ts-node
来帮我们查找 ts
文件。
$ npm i -D shelljs @types/shelljs ts-node
复制代码
在根目录新建 renameJS.ts
:
import * as shelljs from "shelljs";
shelljs
.find("src") // 查找src文件夹,并返回一个数组
.filter((file) => file.match(/\.jsx?$/)) // 过滤出 js/jsx 文件
.forEach((file) => {
let newName = file.replace(/\.j(sx?)$/, ".t$1");
shelljs.mv(file, newName); // 重命名
});
复制代码
shell
的 mv
命令为移动(moving)的意思,其实是用 cp
和 rm
来完成的。
配置重命名脚本(package.json):
{
"scripts": {
// ...
"rename-js": "ts-node renameJS.ts"
}
}
复制代码
将 webpack
和 package
的两处入口文件修改:jsx
-> tsx
修改类型检查规则
-
tsconfig.json
{ "compilerOptions": { // "allowJs": true, // "checkJs": true, "strict": false /* Additional Checks */ // ... 全都关闭(false) } } 复制代码
这样宽松的检查规则,会减少大部分的报错;但新增的 ts
文件也失去了严格的类型检查。
所以,这更适合当过渡策略。
严格策略
所谓严格策略,即开启最严格的类型检查规则,处理所有的报错。
首先也需要对文件重命名,见【宽松策略/重命名】。
类型检查规则(tsconfig.json
),类型检查相关配置都打开(true
):
{
"compilerOptions": {
/* Strict Type-Checking Options */
"strict": true
// ...
/* Additional Checks */
// ...
}
}
复制代码