- 什么是 TypeScript?
- 官方定义:Typed JavaScript at Any Scale.
- 添加了类型系统的 js,适用于任何规模的项目。
- 从 TypeScript 的名字就可以看出来,「类型」是其最核心的特性。
- js 是一门非常灵活的编程语言,以下这些特点,你既可以将其视作是 js 的优点(灵活),也可以将其视作是 js 的缺点(随便)
- 它没有类型约束,一个变量可能初始化时是字符串,过一会儿又被赋值为数字。
- 由于隐式类型转换的存在,有的变量的类型很难在运行前就确定。
- ……
- ts 的类型系统,在很大程度上弥补了 js 在类型上表现得很“随便”的缺点
- 类型系统按照「类型检查的时机」来分类,可以分为动态类型和静态类型
- 动态类型:在运行时才会进行类型检查,这种语言的类型错误往往会导致运行时错误。
- 静态类型:编译阶段就能确定每个变量的类型,这种语言的类型错误往往会导致语法错误。
- js 是一门动态的解释型语言,没有编译阶段
- ts 是一门静态的编译型语言,在运行前需要先编译为 js,而在编译阶段就会进行类型检查
// js
let foo = 1;
foo.split(' ');
运行时报错:Uncaught TypeError: foo.split is not a function
在 js 中,上述写法会在运行时会报错(foo.split 不是一个函数),造成线上 bug。
思考:这种写法,为什么 js 没法在运行之前就给我们报错呢?
因为在 js 中,对于变量类型的约束是很随便的,这就意味着,从声明变量 foo let foo = 1;
到调用 foo 身上的 split 方法 foo.split(' ');
之间,我们可以随便去变更 foo 的类型。
let foo = 1;
foo = '1';
foo.split(' ');
foo = '1';
这种中途变更变量类型的做法,在 js 中是被允许的,所以 js 没法确定当执行 foo.split(' ')
时并能确定它是数字类型。而这种中途变更类型的做法,在 ts 中默认是不被允许的行为,所以 ts 中会及时报错。
// ts
let foo = 1; // let foo: number = 1;
foo.split(' ');
运行前报错:Property ‘split’ does not exist on type ‘number’.
在 ts 中,这种写法编译时(在运行代码之前)就会报错(数字没有 split 方法),无法通过编译。
let foo = 1;
不去手动声明变量 foo 的类型,也能在变量初始化时自动推论出它是一个 number 类型。这得益于 ts 强大的类型推导机制,也就是说这种写法其实等效于 let foo: number = 1;
- ts 强大的“类型推论”,使得大部分 js 代码都只需要经过少量的修改(或者完全不用修改)就变成 ts 代码
- 类型系统按照「是否允许隐式类型转换」来分类,可以分为强类型和弱类型
- 弱类型:允许隐式类型转换
- 强类型:不允许隐式类型转换
- js 和 ts 都是弱类型
- Python 是强类型
弱类型:
// js 或 ts
console.log(1 + '1');
// 打印出字符串 '11'
强类型:
print(1 + '1')
# TypeError: unsupported operand type(s) for +: 'int' and 'str'
# 若要修复该错误,需要进行强制类型转换
print(str(1) + '1')
# 打印出字符串 '11'
- ts 的类型系统体现了它的核心设计理念:在完整保留 js 运行时行为的基础上,通过引入静态类型系统来提高代码的可维护性,减少可能出现的 bug
- 大型项目 vs. 中小型项目
- 大型项目:适合 ts
- 中小型项目:适合 js(其实也适合 ts)
- ts 非常适用于大型项目——这是显而易见的,类型系统可以为大型项目带来更高的可维护性,以及更少的 bug
- 在中小型项目中推行 ts 的最大障碍就是认为使用 ts 需要写额外的代码,降低开发效率。但事实上,由于有类型推论,大部分类型都不需要手动声明了。相反,ts 增强了编辑器(IDE)的功能,包括代码补全、接口提示、跳转到定义、代码重构等,这在很大程度上提高了开发效率。而且 ts 有近百个编译选项,如果你认为类型检查过于严格,那么可以通过修改编译选项来降低类型检查的标准。
- ts 还可以和 js 共存。这意味着如果你有一个使用 js 开发的旧项目,又想使用 ts 的特性,那么你不需要急着把整个项目都迁移到 ts,你可以使用 ts 编写新文件,然后在后续更迭中逐步迁移旧文件。如果一些 js 文件的迁移成本太高,ts 也提供了一个方案,你可以在不修改 js 文件的前提下,编写一个类型声明文件,实现旧项目的渐进式迁移。
- 事实上,就算你从来没学习过 ts,你也可能已经在不知不觉中使用到了 ts —— 在 VSCode 编辑器中编写 js 时,代码补全和接口提示等功能就是通过 TypeScript Language Service 实现的
- 一些第三方库原生支持了 ts,在使用时就能获得代码补全了,比如 Vue 3.0
- 有一些第三方库原生不支持 ts,但是可以通过安装社区维护的类型声明库(比如通过运行
npm install --save-dev @types/react
来安装 React 的类型声明库)来获得代码补全能力——不管是在 js 项目中还是在 ts 中项目中都是支持的: - ts 的发展已经深入到前端社区的方方面面了,任何规模的项目都或多或少得到了 ts 的支持
- ts 是添加了类型系统的 js,适用于任何规模的项目。
- ts 是一门静态类型、弱类型的语言。
- ts 是完全兼容 js 的,它不会修改 js 运行时的特性。
- ts 可以编译为 js,然后运行在浏览器、Node.js 等任何能运行 js 的环境中。
- ts 拥有很多编译选项,类型检查的严格程度由你决定。
- ts 可以和 js 共存,这意味着 js 项目能够渐进式的迁移到 ts。
- ts 增强了编辑器(IDE)的功能,提供了代码补全、接口提示、跳转到定义、代码重构等能力。
- ts 拥有活跃的社区,大多数常用的第三方库都提供了类型声明。
- ts 与标准同步发展,符合最新的 ECMAScript 标准(stage 3)。
- ts 只会在编译时对类型进行静态检查,如果发现有错误,编译的时候就会报错
**noEmitOnError**
**noEmitOnError**
默认值是**false**
,这意味着在 ts 编译的时候即使报错了,还是会生成编译结果- 如果要在报错的时候终止 js 文件的生成,可以在
**tsconfig.json**
中配置**noEmitOnError**
为**true**
即可