JavaScript

TypeScript 介绍

随着前端工程化的快速发展, TypeScript 变得越来越受欢迎,它已经成为前端开发人员必备技能。 TypeScript 最初是由微软开发并开源的一种编程语言,自2012年10月发布首个公开版本以来,它已得到了人们的广泛认可。TypeScript 发展至今,已经成为很多大型项目的标配,其提供的静态类型系统,大大增强了代码的可读性、可维护性和代码质量。同时,它提供最新的JavaScript特性,能让我们构建更加健壮的组件,新版本不断迭代更新,编写前端代码也越来越香。

1 为什么使用 TypeScript


微软提出 TypeScript 主要是为了实现两个目标:为 JavaScript 提供可选的类型系统,兼容当前及未来的 JavaScript 特性。首先类型系统能够提高代码的质量和可维护性,国内外大型团队经过不断实践后得出一些结论:

  • 类型有利于代码的重构,它有利于编译器在编译时而不是运行时发现错误;
  • 类型是出色的文档形式之一,良好的函数声明胜过冗长的代码注释,通过声明即可知道具体的实现;

像其他语言都有类型的存在,如果强加于 JavaScript 之上,类型可能会有一些不必要的复杂性,而 TypeScript 在两者之间做了折中处理尽可能地降低了入门门槛,它使 JavaScript 即 TypeScript ,为 JavaScript 提供了编译时的类型安全。TypeScript 类型完全是可选的,原来的 .js 文件可以直接被重命名为 .ts ,ts 文件可以被编译成标准的 JavaScript 代码,并保证编译后的代码全部兼容,它也被成为 JavaScript 的 “超集”。没有类型的 JavaScript 语法虽然简单灵活,使用的变量是弱类型,但是比较难以掌握,TypeScript 提供的静态类型检查,很好的弥补了 JavaScript 的不足。

TypeScript 类型可以是隐式的也可以是显式的,它会尽可能安全地推断类型,以便在代码开发过程中以极小的成本为你提供类型安全,也可以使用显式的声明类型注解让编译器编译出我们想要的内容,更重要的是为下一个必须阅读代码的开发人员理解代码逻辑。

类型错误也不会阻止JavaScript 的正常运行,为了方便把 JavaScript 代码迁移到 TypeScript,即使存在编译错误,TypeScript 也会被编译出完整的 JavaScript 代码,这与其他语言的编译器工作方式有很大不同,这也正是 TypeScript 被青睐的另一个原因。

TypeScript 的特点还有很多比如下面这些:

  • 免费开源,使用 Apache 授权协议;
  • 基于ECMAScript 标准进行拓展,是 JavaScript 的超集;
  • 添加了可选静态类型、类和模块;
  • 可以编译为可读的、符合ECMAScript 规范的 JavaScript;
  • 成为一款跨平台的工具,支持所有的浏览器、主机和操作系统;
  • 保证可以与 JavaScript 代码一起使用,无须修改(这一点保证了 JavaScript 项目可以向 TypeScript 平滑迁移);
  • 文件扩展名是 ts/tsx;
  • 编译时检查,不污染运行时;

总的来说我们没有理由不使用 TypeScript, 因为 JavaScript 就是 TypeScript,TypeScript 可以让 JavaScript 更美好。

2 开始使用 TypeScript

2.1 安装 TypeScript 依赖环境

TypeScript 开发环境搭建非常简单,大部分前端工程都集成了 TypeScript 只需安装依赖增加配置即可。所有前端项目都离不开 NodeJS 和 npm 工具,npm 命令安装 TypeScript,通常TypeScript 自带的 tsc 并不能直接运行TypeScript 代码,因此我们还会安装 TypeScript 的运行时 ts-node

npm install --save-dev typescript ts-node

2.1.1 集成 Babel

前端工程大都离不开 Babel ,我们需要将 TypScript 和 Babel 结合使用,TypeScript 编译器负责对代码进行静态类型检查,Babel 负责将TypeScript 代码转译为可以执行的 JavaScript 代码:

Babel 与 TypeScript 结合的关键依赖 @babel/preset-typescript,它提供了从 TypeScript 代码中移除类型相关代码(如,类型注解,接口,类型文件等),并在 babel.config.js 文件添加配置选项:

npm install -D @babel/preset-typescript

// babel.config.js
{
"presets

": [
// ...
"@babel/preset-typescript"
]
}

2.1.2 集成 ESlint

代码检查是项目的重要组成部分,TypeScript 自身的约束相对简单只可以发现一些代码错误并不会帮助我们统一代码风格,当项目越来越庞大,开发人员越来越多时,代码风格的约束还是必不可少的。我们可以借助 ESLint对代码风格进行约束,为了让 eslint 来解析 TypeScript 代码我们需要安装解析器 @typescript-eslint/parser 和 插件 @typescript-eslint/eslint-plugin:

npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin

注意: @typescript-eslint/parser 和 @typescript-eslint/eslint-plugin 必须使用相同的版本
在 .eslintrc.js 配置文件中添加选项:

"parser": "@typescript-eslint/parser",
      "plugins": ["@typescript-eslint"],


// 可以直接启用推荐的规则
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
]
// 也可以选择自定义规则
"rules": {
"@typescript-eslint/no-use-before-define": "error",
// ...
}

自定义规则选项具体解读:

2.2 配置 TypeScript

TypeScript 本身提供了只使用参数在命令行编译 TypeScript 文件,但是在实际项目开发时我们都会使用 tsconfig.json ,如果项目中没有此文件,可以手动创建也可以使用命令行创建(tsc —init)。使用 TypeScript 初期仅需要一份默认的 tsconfig.json 即可,它包含了一下基本的编译选项相关信息,当我们需要定制编译选项时就需要去了解每一项具体的含义,编译选项解读如下:

2.严格的类型检查选项:

  • strict: 是否启用严格类型检查选项,可选 ture | false
  • allowUnreachableCode: 是否允许不可达的代码出现,可选 ture | false
  • allowUnusedLabels: 是否报告未使用的标签错误,可选 ture | false
  • noImplicitAny: 当在表达式和声明上有隐式的 any 时是否报错,可选 ture | false
  • strictNullChecks: 是否启用严格的 null 检查,可选 ture | false
  • noImplicitThis: 当 this 表达式的值为 any 时,生成一个错误,可选 ture | false
  • alwaysStrict: 是否以严格模式检查每个模块,并在每个文件里加入 use strict,可选 ture | false
  • noImplicitReturns: 当函数有的分支没有返回值时是否会报错,可选 ture | false
  • noFallthroughCasesInSwitch: 表示是否报告 switch 语句的 case 分支落空(fallthrough)错误;

3.模块解析选项:

  • moduleResolution: 模块解析策略默认为 node 比较通用的一种方式基
  • commonjs 模块标准,另一种是 classic 适用于其他 module 标准,如 amd、 umd、 esnext 等等
  • baseUrl: “./“ 用于解析非相对模块名称的根目录
  • paths: 模块名到基于 baseUrl 的路径映射的列表,格式 {}
  • rootDirs: 根文件夹列表,其做好内容表示项目运行时的结果内容,格式 []
  • typeRoots: 包含类型声明的文件列表,格式 [“./types”] ,相对于配置文件的路径解析;
  • allowSyntheticDefaultImports: 是否允许从没有设置默认导出的模块中默认导入

4.Source Map 选项:

  • sourceRoot: ./ 指定调试器应该找到 TypeScript 文件而不是源文件的位置
  • mapRoot: ./ 指定调试器应该找到映射文件而不是生成文件的位置
  • inlineSourceMap: 是否生成单个 sourceMap 文件,不是将 sourceMap 生成不同的文件
  • inlineSources: 是否将代码与 sourceMap 生成到一个文件中,要求同时设置 inlineSourceMap 和 sourceMap 属性

5.其它选项:

  • experimentalDecorators: 是否启用装饰器
  • emitDecoratorMetadata: 是否为装饰器提供元数据的支持

6.还可以使用include 和 exclude 选项来指定编译器需要和不需要编译的文件,一般增加必要的 exclude 文件会提升编译性能:

"exclude": [
    "node_modules",
    "dist"
...
  ],

2.3 TypeScript 类型注解

熟悉了 TypeScript 的相关配置,再来看一看 TypeScript 提供的基本类型,下图是与 ES6 类型的对比:

图中蓝色的为基本类型,红色为 TypeScript 支持的特殊类型