boolean
布尔值是最基础的数据类型,在TypeScript中使用boolean定义 布尔值类型:
let isDone: boolean = false;// 编译通过// 注意,使用构造函数 Boolean 创造的对象不是布尔值let createdByNewBoolean: boolean = new Boolean(1);// Type 'Boolean' is not assignable to type 'boolean'.// 'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible// 事实上new Boolean() 返回的是一个Boolean对象let createdByNewBoolean: Boolean = new Boolean(1);// 直接调用 Boolean 也可以返回一个 boolean 类型let createdByBoolean: boolean = Boolean(1);
在TypeScript中,boolean是JavaScript中的基本类型,而Boolean是JavaScript中的构造函数。
number
使用number定义数值类型:
let decLiteral: number = 6;let hexLiteral: number = 0xf00d;// ES6 中的二进制表示法let binaryLiteral: number = 0b1010;// ES6 中的八进制表示法let octalLiteral: number = 0o744;let notANumber: number = NaN;let infinityNumber: number = Infinity;
string
使用string定义字符串类型:
let myName: string = 'Zepong';let myAge: number = 25;// 模版字符串let sentence: string = `hello my name is ${myName},I'll be ${myAge + 1} years old next month.`;
any
any用来表示允许赋值为任意类型,一个变量设在了any后相当于对该变量关闭了TypeScript的类型检查,所以在使用TypeScript时,不建议使用any类型。
如果是一个普通类型,在赋值的过程中改变类型是不被允许的:
let myFavoriteNumber: string = 'seven';myFavoriteNumber = 7;// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.
但是如果是any类型,则允许赋值为任意类型:
let myFavoriteNumber: any = 'seven';myFavoriteNumber = 7;
变量如果在声明的时候未指定类型,那么它会被识别为any类型(隐性的any)
nuknown
TypeScript3.0中引入了新的nuknown类型,它是any类型对应的安全类型。
unknown和any的主要区别是unknown类型会更加严格:在对unknown类型执行大多数操作之前,我们必须进行某种形式的检查,而对any类型的值执行操作之前,不必进行任何检查。
我们可以看一下分别赋值给any和unknown的示例代码:
any:
let value: any;value = true; // okvalue = 100; // okvalue = 'hi ts'; // okvalue = []; // okvalue = {}; // ok// 在上述例子中,变量value被定义成any,也因此TypeScript认为以下所有的操作都是类型正确的let value1: unknown = value; // oklet value2: any = value; // oklet value3: boolean = value; // oklet value4: string = value; // oklet value5: object = value; // okvalue.foo.bar; // okvalue.trim(); // okvalue(); // ok
使用any类型,可以很容易的编写类型正确但是执行异常的代码,如果我们使用any类型,就无法享受TypeScript大量的保护机制。
unknown:
let value: unknown;value = true; // okvalue = 100; // okvalue = 'hi ts'; // okvalue = []; // okvalue = {}; // ok// 当我们尝试将类型为unknown的值赋值给其他类型的变量是会发生什么?let value1: unknown = value; // oklet value2: any = value; // oklet value3: boolean = value; // errorlet value4: string = value; // errorlet value5: object = value; // error
unknown类型只能被赋值给any类型和unknown类型本身。直观的说,这是有道理的:只能够保存任意类型的容器才能保存unknown类型的值,毕竟我们都知道变量中存储了什么类型的值。
void(空值)
JavaScript没有空值的概念,在TypeScript中可以使用void表示没有任何返回值的函数:
const alertName = () => :void {alert('my name is zepong');}
如果声明一个void类型的变量是没有什么实质性的作用,因为只能将它赋值为undefined和null:
let unusable: void = undefined;
never
never类型表示的是那些永不存在的值的类型。例如never类型是那些总是会抛出异常或者根本就不会有返回值的函数表达式或者箭头函数表达式的返回值类型。
never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或者可以赋值给never类型(除了never本身)。即使是any也不能赋值给never。
// 返回never的函数必须存在无法达到的终点function error(message: string): never {throw new Error(message);}// 推断的返回值类型为neverfunction fail() {return error("Something failed");}// 返回never的函数必须存在无法达到的终点function infiniteLoop(): never {while (true) {}}
object
object表示非原始数据,也就是除了number、string、boolean、symbol、null、undefiend之外的类型
// {}用来指定对象中可以包含哪些属性// 语法 {属性名: 属性值, 属性名: 属性值,}// 在属性名后面加上?,表示属性是可选的let a: {name: string, age?: number};a = {name: '李', age: 123};// [propName: string]: any 表示任意类型的属性let b: {name: string, [propName: string]: any};b = {name: '李', age: 123};// 设置函数结构的类型什么声明// 语法:(形参: 类型, 形参: 类型, ...) => 返回值let c: (a: number, b: number) => number;
array
TypeScript像JavaScript一样可以操作数组元素。有两种方式定义数组:
第一种可以直接在元素类型后面接上[],表示由此类型元素组成的一个数组
let list: number[] = [1, 2, 3];
第二种方式是使用数组泛型,Array<元素类型>:
let list: Array<number> = [1, 2, 3];
tuple(元组)
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。
let x: [string, number];x = ['hello', 10]; // OKx = [10, 'hello']; // Error
enum(枚举)
使用枚举我们可以定义一些带名字的常量,可以清晰的表达意图或者创建一组有区别的用例。
枚举按照枚举成员的类型可以归位两类:数字枚举类型和字符串枚举类型;
// 枚举使用 enum 关键词来声明一个枚举,数字枚举和字符串枚举的区别就是枚举成员是常数还是字符串;// 01-数字枚举,声明了一个枚举成员均不带初始化器的枚举,// 该枚举的成员值从 0 开始,依次递增enum NumChineseZodiac {rat,cattle,tiger,rabbit,dragon}// 02-字符串枚举enum StrChineseZodiac {rat = 'rat',cattle = 'cattle',tiger = 'tiger',rabbit = 'rabbit',dragon = 'dragon'}
枚举被编译之后,本质为键值对形式的对象,但是这个行为会因为枚举声明的方式以及枚举成员类型的不同,编译之后的结果也会不同。
数字枚举:
// 数字枚举的声明可以分为两大类,带有初始化器和不带初始化器// 01-不带初始化器,枚举成员默认从 0 开始,依次递增;enum NumEnum1 { one, two }NumEnum1.one => 0NumEnum1.two => 1// 02-带有初始化器,这种又可以分为两种:// 02-01-使用初始化器并指定初始化的常数,// 未使用初始化器的成员取值是在上一个成员的基础上 +1;enum NumEnum2 {one = 10,two,three = 20,four}NumEnum2.two => 11NumEnum2.four => 21// 02-02-使用初始化器并且初始化值是对已经声明的枚举的枚举成员的引用enum NumEnum3 {one = NumEnum2.four,two}NumEnum3.one => 21NumEnum3.two => 22
数字枚举在经过编译之后会生成反向映射表,就是除了生成键值对的集合,还会生成值键对的集合;
需要注意的点:
- 不能随意摆放不带初始化值的枚举
- 数字枚举可以反向映射,字符串枚举不行
