相比于JavaScript,TypeScript最大的差异点就在于数据类型。TypeScript具备静态类型检查功能,可以在编译期间快速定位类型错误的问题。
TypeScript的基本类型包括Number、Boolean、String、Symbol、Void、Null和Undefined类型,以及所有用户定义的枚举类型。
1.Number
Number类型对应于JavaScript中的Number类型,用来表示双精度64位格式IEEE 754浮点值。关键字“number”代表Number类型。
以下是一个例子。
代码 3-3 type/primitive-type/number-type.ts
其中的变量说明如下。
● 变量x显式指定了Number类型。
● 变量y和z并没有指定类型,TypeScript会根据所赋的值来推导出类型。
● 变量s是通过“Number.toFixed(fractionDigits?:number):string”方法来返回的。
通过typeof函数,我们能够在控制台上看到各个变量的类型。
在这里读者可能会感到疑惑,为什么我们将变量x声明为Number类型,但实际的类型仍然是Undefined?
在TypeScript规范中有这么一段话:“The undefined literal denotes the value given to all uninitialized variables and is the one and only value of the Undefined type.”意思是,只要是未赋值的变量都是Undefined类型的。
所以,我们给变量x赋上初始值1。
在控制台上再次查看该变量的类型,此时,变量x就是Number类型的了。
2.Boolean
Boolean类型对应于JavaScript中的Boolean类型,用来表示true或false的逻辑值。关键字“boolean”代表Boolean类型。
观察下面这个例子。
代码 3-4 type/primitive-type/boolean-type.ts
其中的变量说明如下。
● 变量b显式指定了Boolean类型。
● 变量yes和no并没有指定类型,TypeScript会根据所赋的值来推导出类型。
通过typeof函数,我们能够在控制台上看到各个变量的类型。
同样地,变量b由于一开始未被赋值,所以类型也是Undefined。当变量b被赋值为false之后,类型变为了Boolean。
3.String
String类型对应于JavaScript中的String类型,用来表示存储为Unicode UTF-16的字符序列。关键字“string”代表String类型。
观察以下例子。
代码 3-5 type/primitive-type/string-type.ts
其中的变量说明如下。
● 变量s显式指定了String类型。
● 变量empty和abc并没有指定类型,TypeScript会根据所赋的值来推导出类型。
● 变量c是通过“String.charAt(pos:number):string”方法来返回的。
通过typeof函数,我们能够在控制台上看到各个变量的类型。
同样地,变量s由于一开始未被赋值,所以类型也是Undefined。当变量s被赋值为false之后,类型变为了String。
4.Symbol
Symbol类型对应于JavaScript中的Symbol类型,用来表示对象属性的键。这些键都是唯一的。关键字“symbol”代表Symbol类型。
Symbol值是使用全局对象Symbol获得的,该对象具有表3-1中所列的方法和属性,可以作为函数被调用。
提示:
全局对象Symbol定义了许多可以与标识符类似的方式使用的Symbol属性。
表3-1 全局对象Symbol的方法和属性
提示:
Symbol对象是在ECMAScript 2015中引入的,所以只能在ECMAScript 2015及以上环境中使用它。
5.Void
如果函数不需要返回值,则使用Void类型。关键字“void”代表Void类型,表示默认值。
Void类型的可能值是null和undefined。Void类型是任意类型的子类型,是Null和Undefined类型的超类型。
提示:
不允许声明Void类型的变量,因为它们没有用处。但是,允许Void作为泛型类型或函数的类型参数。
6.Null
Null类型对应于JavaScript中的Null类型。
null是代表引用Null类型的值。无法直接引用Null类型本身。
Null类型是除Undefined类型外的所有类型的子类型。这意味着,null可以被认为是所有基本类型、对象类型、联合类型、交集类型和类型参数的有效值,甚至包括Number和Boolean类型。
观察以下例子。
代码 3-6 type/primitive-type/null-type.ts
变量n、x的声明是合法的。变量e的声明是非法的,因为不能直接引用Null类型。
7.Undefined
Undefined类型与JavaScript中的Undefined类型一致。
undefined表示未初始化变量的值,并且是Undefined类型的唯一值。无法直接引用Undefined类型本身。
Undefined类型是所有类型的子类型。这意味着,undefined可以被认为是所有基本类型、对象类型、联合类型、交集类型和类型参数的有效值。
观察以下例子。
代码 3-7 type/primitive-type/undefined-type.ts
变量n、x的声明是合法的。变量e的声明是非法的,因为不能直接引用Undefined类型。
8. 枚举
枚举类型是不同用户定义的Number类型的子类型。枚举类型使用枚举声明及类型引用声明。
枚举类型可分配给Number类型,反之亦然,但不同的枚举类型不能彼此分配。
以下是一个枚举类型示例。
有关枚举类型的详细内容,后续会继续探讨。
在面向对象编程语言中,对象(Object)是非常重要的一种类型。对象类型由属性、调用签名、构造签名和索引签名等成员组成。
类和接口类型、数组类型、元组类型、函数类型、构造函数类型都是对象类型。TypeScript可以创建对象类型。
有时需要描述“在编写应用时还不知道”的变量类型。这些值可能来自动态内容,例如,来自用户或第三方库。在这些情况下,可以选择退出类型检查,并让这些值通过编译器的检查。为此,使用任意类型来标记这种类型。
1. 用 any 表示任意类型
在下面的例子中,任意类型用any来表示。
代码 3-8 type/any-type/any-type.ts
任意类型使用了现有JavaScript的强大方法,允许在编译期间选择加入和退出类型检查。任意类型与对象类型有些类似。但是,对象类型的变量只允许被分配任意值,而不能在它们上调用任意方法,这是与任意类型最大的差异点。
2. 用 Object 表示任意类型
观察下面的例子。
代码 3-9 type/any-type/any-function.ts
notSure变量所使用的方法在编译期间不会有任何问题,但是prettySure变量会报“error TS2339:Property'toFixed'does not exist on type'Object'.”错误,因为toFixed()不是Object 类型的方法。
例如,有一个数组,该数组中有不同类型的元素。
我们可以对该数组中的元素执行替换或者追加操作。替换的元素可以与被替换的元素类型不一致。比如,将数组中的true、'free'元素替换为2、3,并追加元素4。
完整示例如下。
代码 3-10 type/any-type/any-array.ts
输出的内容如下:
可以看到,原有的true和'free'分别是Boolean和String类型的,都被替换成了Number类型。
联合类型表示可能具有多个不同表示之一的值。联合类型“A|B”的值是类型A或类型B的值。
观察下面的例子。
变量x被声明为String和Number的联合类型,因此,其被赋值为"hello"和42都是正确的。而当变量x被赋值为Boolean类型时,会报“error TS2322:Type'false|0'is not assignable to type'string|number'.”错误。
交集类型是把多种类型叠加到一起形成的一种新类型,新类型包含了被叠加类型的特性。
示例如下。
代码 3-11 type/intersection-type/intersection-type.ts