02-React添加TS

JS 本身是一门动态类型语言,有了对静态类型的需求。TS 诞生

1. React + TS

# 直接创建
npx create-react-app my-app --template typescript

项目改变:

  1. .js => .tsx
  2. 增加了 tsconfig.json 文件
{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}

1. tsconfig.json

tsconfig.json 是 TS 的配置文件,TS 是开发环境中的语言,浏览器不认识 TS

  • 在生产阶段早期是通过webpack 插件 ts-loader 将 TS 编译成 JS
  • ts-loader 在内部是调用了 TS 的官方编译器 tsc。所以 ts-loadertsc 共享 tsconfig.json
  • 存在问题:ts-loader 将 TS 编译成 JS,为了兼容低版本的浏览器,一般还会通过 babel 转化成 es5 低版本的 JS。 所以这个过程是这样的 TS > TS 编译器 > JS > Babel > JS (es5)
  • Babel 7 之前是不支持 TS 的,所以整个的解析链路很长。在 Babel7 中做了一个改变,使用 babel-loader 就能直接解析 TS, react 脚手架中使用的也是 babel-loader,配置文件不变依然是 tsconfig.json

Babel 是一个 JS 编译器

主要用于将采用 ECMAScript 2015+(es6+)语法编写的代码转换为向后兼容的 JS 语法,以便能够运行在当前和旧版本的浏览器或其他环境中

配置文档

编译器启动时,首先会读取 tsconfig.json,以获取有关如何编译项目的说明(例如,要编译哪些源文件,在哪里存储输出等)。 现在,我们来研究一下上图出现的比较常见的编译器 tsconfig 选项。

"target": "es5"

这个属性定义了你编译后的目标javascript版本一般来说,我们需要让他编译为es5,这样就可以被主流浏览器解读了。当然,你说我的react代码不是给浏览器看的,比如说,你使用的是react-native 开发手机app,那么这里的选项可以选择es6。除了e s5和es6,我们还有很多其他常见的选项。ES5,ES6/ES2015,ES2016,ES2017,ES2018,ES2019,ES2020,ESNext,等等等等。

"lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ]

这个属性列出了编译期间需要被包括进来的库文件。通过这些库文件,告诉typescript编译器可以使用哪些功能。比如说,我们这里有一个dom的库文件这个文件会告诉编译器DOM API的接口,所以当我们在ts代码中使用 DOM 的时候,比如说执行"document. getElementById("root")"这句话的时候,编译器就会知道该如何进行检查。如果我们不设置这个选项,那么编译器也有自己默认的库文件列表。

"allowJs": true

允许混合编译JavaScript文件。(允许编译器编译JS,JSX文件)

"skipLibCheck": true

忽略所有的声明文件( *.d.ts)的类型检查。

"esModuleInterop": true

这个选项允许我们使用commonjs的方式import默认文件。

"allowSyntheticDefaultImports": true

允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。

"strict": true

启用所有严格类型检查选项。

"forceConsistentCasingInFileNames": true

禁止对同一个文件的不一致的引用。

"noFallthroughCasesInSwitch": true

不允许switch的case语句贯穿。

switch语句,除非明确地中断流程,否则每次条件判断后都贯穿到下一个case条件。

"module": "esnext"

这里配置的是我们代码的模块系统,比较常见的有Node.js的CommonJS系统,ES6标准的esnext系统以及requirejs的AMD系统。我们这里使用的是ES6标准的esnext系统,不过如果把这里换成CommonJs也是可以的。

"moduleResolution": "node"

这个选项决定了我们编译器的工作方式,也决定了我们各个文件之间调用、import的工作流程。这里曾经有两个选项,"node" and "classic",但是"c lassic"这个选项在2019年12月就已经废弃了。

"resolveJsonModule": true

译选项可允许从 .json 中导入、导出其类型。(详情看示例1:)

"isolatedModules": true

将每个文件作为单独的模块

"noEmit": true

开启这个选项表示当发生错误的时候,编译器不会生成 JavaScript 代码。

"jsx": "react-jsx"

允许编译器支持编译 react-jsx 代码。

示例1:

settings.json

{
    "repo": "TypeScript",
    "dry": false,
    "debug": false
}

index.ts

import settings from "./settings.json";

settings.debug === true;  // OK
settings.dry === 2;  // Error: '===' 不能用于比较 boolean 和 number 类型

tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "resolveJsonModule": true,
        "esModuleInterop": true
    }
}

参考: 编译器选项 https://www.tslang.cn/docs/handbook/compiler-options.html