类型系统
从 TypeScript 的名字就可以看出来,类型是其最核心的特性。
同时 TypeScript 也是 JavaScript 的超集,我们知道 JavaScript 是一门非常灵活的编程语言:
- JavaScript 没有类型约束,一个变量可能初始化时是字符串,过一会又被赋值为数字
- 由于隐式类型转换的存在,有的变量的类型很难在运行前就确定
- 基于原型的面向对象编程,使得原型上的属性或方法可以在运行时被修改
- 函数是 JavaScript 中的一等公民,可以赋值给变量,也可以当做参数或返回值
JavaScript 这种灵活性是一把双刃剑,使得 JavaScript 代码质量参差不齐,维护成本高,运行时错误多。
而 TypeScript 的类型系统,在很大程度上弥补了 JavaScript 的缺点。
TypeScript 是静态类型
类型系统按照 类型检查的时机 来分类,可以分为静态类型和动态类型。
动态类型是指在运行时才会进行类型检查,这种语言的类型错误往往会导致运行时错误。
JavaScript 是一门解释性语言,没有编译阶段,所以它是动态类型,以下代码在运行时会报错:
let foo = 1;
foo.split('');
// Uncaught TypeError: foo.split is not a function
// 运行时会报错(foo.split 不是一个函数),造成线上 bug
静态类型是指在编译阶段就能确定每个变量的类型,这种语言的类型错误往往会导致语法错误。
TypeScript 在运行前需要先编译为 JavaScript,而在编译阶段就会进行类型检查,所以 TypeScript 是静态类型,这段 TypeScript 代码在编译阶段就会报错:
let foo = 1;
foo.split('');
// Property 'split' does not exist on type 'number'.
// 编译时会报错(数字没有 split 方法),无法通过编译
这段 TypeScript 代码和 JavaScript 代码并没有太大的区别,因为大部分的 JavaScript 代码都只需要经过少量的修改(或者完全不用修改)就能变成 TypeScript 代码,这得益于 TypeScript 强大的类型推论,即使不去手动声明变量 foo 的类型,也能在变量初始化时自动推论出它是一个 number 类型。
所以完整的 TypeScript 代码是这样的:
let foo: number = 1;
foo.split('');
// Property 'split' does not exist on type 'number'.
// 编译时会报错(数字没有 split 方法),无法通过编译
TypeScript 是弱类型
类型系统按照 是否允许隐式类型转换 来分类,可以分为强类型和弱类型。
以下代码在 JavaScript 和 TypeScript 中都是可以正常运行的,运行时数字1会被隐式类型转换为字符串’1’,加号’+'被识别为字符串拼接,所以打印出结果是字符串 ‘11’。
console.log(1 + '1');
作为对比,Python是强类型语言,以下代码在运行时会报错:
print(1 + '1')
# TypeError: unsupported operand type(s) for +: 'int' and 'str'
如要修复该错误,需要进行强制类型转换:
print(str(1) + '1')
# 打印出字符串'11'
强/弱是相对的,Python 在处理整型和浮点型相加时,会将整型隐式转换为浮点型,但是这并不影响 Python 是强类型语言的结论,因为大部分情况下 Python 并不会进行隐式类型转换。相比而言,JavaScript 和 TypeScript 中不管加号两侧是什么类型,都可以通过隐式类型转换计算出一个结果——而不是报错——所以 JavaScript 和 TypeScript 都是弱类型。
这样的类型系统体现了 TypeScript 的核心设计理念:在完整保留 JavaScript 运行时行为的基础上,通过引入静态类型系统来提高代码的可维护性,减少可能出现的bug。
总结: 什么是 TypeScript
- TypeScript 是添加了类型系统的 JavaScript,适用于任何规模的项目。
- TypeScript 是一门静态类型、弱类型的语言。
- TypeScript 是完全兼容 JavaScript 的,它不会修改 JavaScript 运行时的特性。
- TypeScript 可以编译为 JavaScript,然后运行在浏览器、Node.js 等任何能运行 JavaScript 的环境中。
- TypeScript 拥有很多编译选项,类型检查的严格程度由你决定。
- TypeScript 可以和 JavaScript 共存,这意味着 JavaScript 项目能够渐进式的迁移到 TypeScript。
- TypeScript 增强了编辑器(IDE)的功能,提供了代码补全、接口提示、跳转到定义、代码重构等能力。
- TypeScript 拥有活跃的社区,大多数常用的第三方库都提供了类型声明。
- TypeScript 与标准同步发展,符合最新的 ECMAScript 标准。