Pasoul / blog

🛠 学习笔记 & 源码分析 & 代码规范 & 数据结构与算法
17 stars 3 forks source link

typescript手册-数据类型 #15

Open Pasoul opened 5 years ago

Pasoul commented 5 years ago

typescript支持几乎与javascript相同的基础数据类型:NumberStringBooleanUndefinedNull,在此基础上,typescript还扩展了voidany等常见类型数据。

基础数据类型声明

// 声明一个number类型变量
let n:number = 2;

typescript,如果未按照类型注解给变量赋值,比如将字符串赋值给n,将会在编译阶段报错: Type '"1"' is not assignable to type 'number'.

// 声明一个布尔类型的变量
let hasMore:boolean = true;
// 声明一个string类型变量
let nickname:string = "zhangsan";
// null和undefined
let un:undefined = undefined;
let nu:null = null;
// 默认情况下null和undefined是所有类型的子类型。 就是说你可以把null和undefined赋值给number类型的变量
let n:number = undefined;

然而,当你设置了--strictNullChecks表示严格校验空值,undefinednull只能赋值给它们各自或者void类型。因为未避免发生不可预知的错误,鼓励使用--strictNullChecks

扩展数据类型

任意值

有时候我们声明一个变量的时候不确定它是什么类型,它有可能是动态的内容,比如用户输入的值,这时我们希望编译器可以直接通过对它们的检查。

// 声明一个任意值类型变量
let notSure:any = "123";
notSure = 123;
notSure = true;

任意值类型在声明数组的时候也非常有用,比如数组的元素的值是任意类型:

let arr:any = [1, '1', true]

空值

通常,我们用空值void声明一个没有返回值的函数,很少用它声明一个变量,因为意义不大,只能赋值undefinednull(严格校验空值的时候,只能赋值undefined

// 声明一个空值类型变量
let empty:void = undefined;
empty = null;

// 声明一个没有返回值的函数
function fn():void {
  console.log("no return value");
}
// 等价于
function fn():void {
  console.log("no return value");
  return undefined;
}
Pasoul commented 5 years ago

数组和元组

数组

typescript中,我们有两种方式声明数组:

第一种:元素类型 + [ ],表示由此类型元素组成的数组

// 声明一个元素全部为number类型的数组
let arr:number[] = [1, 2, 3];
// 如果其中某些元素不是number类型,将会编译出错,比如下面将会报错:
// Type 'string' is not assignable to type 'number'
// Type 'true' is not assignable to type 'number'
let incorrectArr:number[] = [1, 2, '3', true];

第二种:数组泛型,Array<元素类型>

// 使用泛型声明数组,数组元素全部为number类型
let arr:Array<number> = [1, 2, 3];

有时,数组的元素类型不能确定,我们可以将元素类型指定为any

// 声明一个元素为任意类型的数组
let arr:any[] = [1, '1', false, undefined, null]

元组

元组类型表示一个已知元素类型长度的数组

// 声明一个元组长度为2,第一个元素类型为number,第二个元素类型为string
let tuple:[number, string];
tuple = [1, 'hello']

如果我们将第一个元素设置成string,编译将会报错:

let tuple:[number, string];
tuple = ['bye', 'hello']
// Type 'string' is not assignable to type 'number'

如果赋值的元组长度大于2,编译将会报错:

let tuple:[number, string];
tuple = [1, 'hello', '设置第三个元素']
Type '[number, string, string]' is not assignable to type '[number, string]'.
Types of property 'length' are incompatible.
Type '3' is not assignable to type '2'.

如果元组长度不足2,编译将会报错:

let tuple:[number, string];
tuple = [1]
Type '[number]' is not assignable to type '[number, string]'.
  Property '1' is missing in type '[number]'

以上两种情况都是赋值的元组长度不能和预设的长度兼容。

越界的元素

如果我们试图通过元组下标来进行越界赋值,比如:

let tuple:[number, string];
tuple = [1, 'hello'];
tuple[3] = 'bye';

编译器将会告知我们:下标3对于长度为2的元组来说越界了

Index '3' is out-of-bounds in tuple of length 2

但是使用pushunshift方法为元组添加元素时,编译不会报错:

let tuple:[number, string];
tuple = [1, 'hello'];
tuple.push('bye');
tuple.unshift(10);

此时越界添加的元素类型为元组中每个类型的联合类型:

简单的举例联合类型就是:

// 声明变量age的类型是联合类型string|number,意味着age可以分别被赋值为number和string类型的值
let age:string|number = 10;
age = '10'

因此元组的越界元素的类型是number|string,如果我们为其新增一个类型为boolean的元素,编译将会报错:

let tuple:[number, string];
tuple = [1, 'hello'];
tuple.push(true);

Argument of type 'true' is not assignable to parameter of type 'string | number'

不建议越界访问元组

虽然可以通过pushunshift方法为元组越界插入一个新元素,但是并不推荐你这么做,同时在typescript中,如果你试图通过下标访问越界元素,你会发现编译抛出异常

let tuple:[number, string];
tuple = [1, 'hello'];
tuple.push('bye');
console.log(tuple[3]);

Index '3' is out-of-bounds in tuple of length 2

因为我们使用元组的初衷就是希望在定义之初,就知道它的元素类型和长度,而不希望在其他地方不小心做了更改。

参考: