一、描述

typescript 的基础类型外,还额外扩充了几个类型,用来增强 typescript 的可用性。

基础类型包括:

  • boolean

二、基本数据类型

1、boolean 布尔类型

boolean 对应的是 js 中的 Boolean,值只有 true 和 false声明方式:

let flag: boolean = false;
flag = true;
flag = '1'; // 报错:Type '"1"' is not assignable to type 'boolean'.

2、number 数字类型

number 是所有浮点数的类型支撑,支持十进制、十六进制、二进制和八进制的字面量.

let num: number = 1;
num = 0xf00d;
num = 0b1010;
num = 0o744;
num = '1'; // 报错:Type '"1"' is not assignable to type 'number'

3、 string 字符串

let str: string = "bob";
str = "smith";
str= `${str} is : aaaaa`; // 转换结果:str = str + " is : aaaaa";
str= []; // 报错:Type 'never[]' is not assignable to type 'string'

如果是 ES6 的语法,比如 ` ` 最终会编译成 ES5 的语法。

4、[] 数组

数组的声明并不是 array,而是通过 元素类型[] 的形式去声明的。

数组中每个数据的类型都是一致的,在初始化的时候就已经定义好

let arr: string[] = ['name'];
arr.push(1); // 报错:Argument of type '1' is not assignable to parameter of type 'string'.

可以发现,如果在这里调用 arr.push(1), 类型检查会报错误,下面的代码会报同样的类型错误:

let arr: string[] = ['name'];
let num: number = 1;
arr.push(num);

当然除了上面 元素类型[] 这种形式声明外,还可以使用泛型去声明数组:Array<元素类型>

let arr: Array<string> = ['1', '2', '3']

5、元组 Tuple

元组一般用来标识一个已知元素数量和类型的数组,虽然是数组,但是类型可以不相同。

定义方式:let x = [元素类型1, 元素类型2, 元素类型3]

let tuple: [string, number] = ['ptbird', 10]; // 编译结果:var tuple = ['ptbird', 10];
tuple[0] = '123';
tuple[0] = 123; // 报错:Type '123' is not assignable to type 'string'

元组是数量类型固定的,因此下面的代码会在类型检查的时候报错误,因为超出了元组的边界

但是这部分在文档中确有一个例子,所以我不确定是文档有误还是使用方式有误,但确实,如果定义了一个元组的长度后,在超出元组的边界,是会提示错误的。

tuple[3] = 123; // 报错:Type '123' is not assignable to type 'undefined'
tuple[3] = '123'; // 报错:Type '"123"' is not assignable to type 'undefined'.

1.jpg

6、Enum 枚举

记得上一次用 Enum 类型还是在写 C 语言的时候...至于 Enum 类型是什么,不想再去阐述。

enum Color {Red, Green, Blue};

let c: Color = Color.Green;

编译结果:

var Color;
(function (Color) {
    Color[Color["Red"] = 0] = "Red";
    Color[Color["Green"] = 1] = "Green";
    Color[Color["Blue"] = 2] = "Blue";
})(Color || (Color = {}));
;
var c = Color.Green;

enum 也类似于数组有索引的,索引默认从 0 开始,不过可以指定这个编号:

enum Color {Red = 1, Green, Blue};
console.log(Color[0]);
console.log(Color[1]);

上面代码编译之后的结果实际上是:

var Color;
(function (Color) {
    Color[Color["Red"] = 1] = "Red";
    Color[Color["Green"] = 2] = "Green";
    Color[Color["Blue"] = 3] = "Blue";
})(Color || (Color = {}));
;
console.log(Color[0]); // undefine
console.log(Color[1]); // Red 

可以发现,指定了 Red = 1 之后,索引 0 就失效了,返回的是 undefined,而 Color[1] 返回的则是 Red.

7、Any 类型

javascript 的很多变量的值可能取决于其他的变量或者是网络请求,因此在编译过程的静态检查中,如果写死了一个类型,之后可能会无法编译通过。

而 Any 类型则是可以避免掉这种类型检查。

let str: any = 'asd';
str = 4;
str = false;
str.toFixed();

上面的语法不会触发类型检查错误,因为 str 定义的是 any,所以 any 应当少使用,不然就失去了 typescript 的意义以及底层 javascript 引擎的优化。

因为 any 的变量不会进行检查,因此 str.toFixed 也是没问题的:

str = false;
str.toFixed();

8、Void

void 一般用于 function 没有返回值的时候使用,也可以给一个变量声明成 void 属性,但是这个本身没什么意义,因为一旦一个变量被声明成了 void 类型,则只能赋值 undefined 以及 null。

如果开启了 staticNullCheck ,则只能赋予 undefined,不能赋予 null,会报错

let val: void;
val = undefined;
val = null; // 开启 staticNullCheck: Type '"asd"' is not assignable to type 'void'. 
val = 'asd'; // Type '"asd"' is not assignable to type 'void'.

声明 function 无返回值

function func(): void {
 console.log('no return value ')
}

如果 return 了一个 非 undefined 或者 null 的值,则会报错:

function func(): void {
    return 1; // 报错:Type '1' is not assignable to type 'void'.
}

9、undefined 和 null

undefined 和 null 都是代表一种类型,没有什么实际的作用,不过因为 null 和 undefined 是所有类型的子类型,因此其实 null 和 undefined 是可以赋值给其他类型的变量的。(不过这一点在严格的类型检查中是不生效的,因此建议使用严格的类型检查)

let val1: undefined = undefined;
let val2: null = null;
let str: string = val2; // 报错

对于 undefined 和 null 如果要进行严格类型检查,则可以通过开启 --strictNullChecks 来进行严格类型检查。

10、Never

never 用来表示用不存在的值的类型,never 类型一般用在抛出异常或者根本不会存在返回值的表达式或者是箭头函数表达式的返回值类型,变量如果被永不为 true 的类型保护所约束时,也可以是 never 类型。

never 类型也是任何类型的子类型,可以赋值给任何的类型,不过没有类型是 never 的子类型,而除了 never 本身可以赋值给 never 之外,其他的是不能复制给 never 的,any 类型也不能赋值给 never 类型。

let val: never;
val = val; // ok
let val2: any = 1;
val = val2; // 报错:Type 'any' is not assignable to type 'never'

一般在抛出异常的时候,方法可以直接 throw Error 给外层的方法去处理,此时可以将函数定义为 never

下面三种情况都可以将 function 定义为 never,有些时候,是通过推断返回值类型的,比如下面第二种情况。

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

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

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

11、Object

object 表示除了 numberstringbooleansymbolnullundefined之外的类型,

因此当一个方法需要传入一个对象参数的时候,则可以使用 object 类型:

function create(o: object | null) : void {
    console.log(o);
}

create({name: 11});
create(null);
create(1); // 报错:Argument of type '1' is not assignable to parameter of type 'object | null'.

上面例子中,o: object | null 是一种联合类型, 因此传入object 类型或者是 null 类型都是 ok 的。

12、类型断言

类型断言 实际上是由开发者主动告知编译器当前变量是什么类型,而并非有编译器去推断类型。

类型断言的 尖括号 语法:

const str: any = "this is a string";

let strLength: number = (<string> str).length;

上面代码中,首先声明了 str 是一个 any 类型的,但是初始化了一个值是 this is a string,并且定义方式是 const, 此时我们能够确定 str 永远就是一个字符串,不可能再有其他的类型。

因此在下面的 strLength 变量的生命中,通过 <string> str 指定了 str 的变量类型,这就是一个断言,通知编译器保证 str 一定是一个 string。

除了 尖括号 语法,还可以通过 as

const str: any = "this is a string";

let strLength: number = (str as string).length;

这两种形式是等价的,不过在 JSX 中的时候,只能够使用 str as string 的形式。