TypeScript 中为了使编写的代码更规范,更有利于维护,增加了类型校验,使得 JavaScript 从弱类型变成强类型

在 TypeScript 中主要给我们提供了以下数据类型

  • 布尔类型(boolean)
  • 数字类型(number)
  • 字符串类型(string)
  • 数组类型(array)
  • Symbol
  • Function
  • Object
  • null 和 undefined
  • 元组类型(tuple)
  • 枚举类型(enum)
  • any
  • void
  • never
  • unknown 3.0 新增
  • 高级类型

TypeScript 中指定了某一类型的变量,其值不能改变为其他类型(除了 any 类型),否则 TypeScript 中会报错,但是编译后的 JavaScript 不出错。

类型注解

类型的定义只需要在变量后面加上 :类型 即可,这种方式称为类型注解。

在 TypeScript 中,类型校验有两种模式,一种是严格模式,一种是非严格模式。一般情况下我们都会选择严格模式,所以下面都是
以严格模式为例**。

基本类型

  1. var flag:boolean=true;
  2. // flag=123; //错误
  3. flag=false; //正确
  4. var num:number=123;
  5. var str:string='this is ts';

数组类型

ts 中定义数组有两种方式:

// 第一种定义数组的方式
 var arr:number[]=[11,22,33]; // 注意后面的 []

// 第二种定义数组的方式,实际上是泛型的应用
var arr:Array<number>=[11,22,33];

此时数组类型中每个元素的值,都必须是指定类型的值。如果不是同一类型的值,可以指定为 any 类型,或者不指定类型。

// any 类型数组
var arr:any[] = [11, '22']
var arr:Array<any> = [11, '22']

// any 类型
var arr:any = [11,'22']

// 高级类型 string | number 类型数组
var arr:Array<number | string> = [11, '22']

元组类型

ts 中新增的一个类型,是数组中的一种,实际上编译为 JS 就是数组。

元组限定了数组中每个元素的类型以及数组元素的个数

let tuple:[number,string]=[123,'this is ts'];

可以为数组中已知元素指定一个类型,指定了类型的位置,不能更改为其他类型。

当访问一个越界的元素,会报错。

tuple.push(2); // 元组的越界问题, 当我们 push 的时候并没有报错
console.log(tuple[3]); // 但是访问的时候会报错

object

object 表示非原始类型,也就是除 number,string,boolean,symbol,null 或 undefined 之外的类型。
使用 object 类型,就可以更好的表示像 Object.create 这样的API。例如:

declare function create(o: object | null): void;

create({ prop: 0 }); // OK
create(null); // OK

create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error

枚举类型

在编写代码逻辑的时候,我们经常用到一些数字与字符串的映射关系,比如 0-男 1-女,还有类型、星期、颜色、月份等。我们在 JS 中处理的方式一般使用数组或者对象。

// 数组方式,通过下标进行映射
var color = ['red', 'blue', 'green']

// 对象方式,通过属性进行映射
var color = {
  0: 'red',
  1: 'blue',
  2: 'green'
}

相对来说,数组限定了映射关系,而对象则比较自由。

ts 提供了一种枚举类型,用于处理这种映射关系。并且,这种关系是相互映射的,而不是单向

enum 枚举名{
  标识符[=整型常数],
  标识符[=整型常数],
   ...
  标识符[=整型常数],
};

与 class 的定义类似:

enum Flag {
  success=1,
  error=0
};
var f:Flag = Flag.error //=> 0
var a:string = Flag[1] //=> success,注意要类型是 string 而不是 Flag,否则会报错

//=> 编译后的代码,可知其创建的就是一个对象
var Flag;
(function (Flag) {
    Flag[Flag["error"] = 0] = "error";
    Flag[Flag["success"] = 1] = "success";
})(Flag || (Flag = {}));

:::warning 注意

  1. 定义时,与类一样,开头不需要使用等号
    2. 与对象区分开,标识符与数字之间使用 = 号相连
    3. 实际上创建的就是对象
    4. 枚举类型的值都是只读的,不能修改:::

标识符可以使用字符串:
**

enum Flag {
  'success'=1
}

如果某个标识符没有指定值,那么值就是其前面一个指定值的递增结果,如果其前面没有指定值的元素,那么其值就是下标。
**

enum Color {
  blue,
  red=3,
  green
}
Color.blue // 0
Color.red // 3
Color.green // 4

any

any 类型就相当于 JS 中定义的变量,任意改变类型都可以。

主要用途有:在数组中使用任意类型的值、给对象中的属性赋予任意类型的值、防止调用对象中的方法报错

var oBox = document.getElementById('box')
oBox.style.color = 'red' // 报错,奇怪的错误

// 只能把 oBox 定义为 any 类型
var oBox:any = document.getElementById('box')
oBox.style.color = 'red'

Object类型的变量只是允许你给它赋任意值,但是却不能够在它上面调用任意的方法,即便它真的有这些方法

let notSure: any = 4;
notSure.ifItExists();
notSure.toFixed();

let prettySure: Object = 4;
prettySure.toFixed(); // 报错

变量如果在声明的时候,未指定其类型,那么它会被识别为 any 类型

let something;
something = 'seven';
something = 7;
something.setName('Tom'); // 严格监测模式下报错,此时 something 是最后一个值的类型 number

等价于

let something: any;
something = 'seven';
something = 7;
something.setName('Tom'); // 严格监测模式下也不会报错

void

void 类型主要用于表示函数没有返回值。

function warnUser(): void {
   console.log("This is my warning message");
}

声明一个void类型的变量没有什么大用,因为此时你只能为它赋予 undefined 和 null:

let unusable: void = undefined;

null 和 undefined

null 和 undefined 也是特殊的数据类型,而且值就是 null 和 undefined,且不可更改。

var num:null;
num = 1 // 报错
num = null // 正确

var bb:undefined;
bb = 1 // 报错
bb = undefined // 正确

如果变量为赋值,那么其值就是 undefined。

var num; // num 为 any 类型
console.log(num) // undefined

// 如果指定了类型
var num:any
console.log(num) // undefined

var num:undefined
console.log(num) // undefined

var num:number
console.log(num) // 严格模式下报错,使用未赋值的变量

:::info 默认情况下 null 和 undefined 是所有类型的子类型。 就是说你可以把 null 和 undefined 赋值给 number 类型的变量。然而,当你指定了 --strictNullChecks 标记,null 和 undefined 只能赋值给 void 和它们各自。 这能避免很多常见的问题。 :::

如果需要在初始的时候不赋值,后期赋予 Number 类型,可以指定多个类型,称为联合类型。

var num:number | undefined;
var num = 1 // 正确

var num:number | undefined | null;

never

never 类型表示的是那些永不存在的值的类型。很少使用。

例如, never类型是那些总是会抛出异常的函数表达式或箭头函数表达式的返回值类型; 变量也可能是 never类型,当它们被永不为真的类型保护所约束时。

never 类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是 never 的子类型或可以赋值给 never 类型(除了 never 本身之外)。 即使 any 也不可以赋值给 never。

// 返回 never 的函数必须存在无法达到的终点
function error(message: string): never {
    throw new Error(message); // 永远抛出错误
}

// 推断的返回值类型为never
function fail() {
    return error("Something failed");
}

// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
    while (true) { // 永远无法结束
    }
}

unknown 3.0 新增

TypeScript 3.0 引入了一个顶级的 unknown 类型。 对照于 any,unknown 是类型安全的。 任何值都可以赋给 unknown但是当没有类型断言或基于控制流的类型细化时unknown不可以赋值给其它类型,除了它自己和 any 外。 同样地,在 unknown 没有被断言或细化到一个确切类型之前,是不允许在其上进行任何操作的