文章目录
数组是十分常用的数据结构,它表示一组有序元素的集合。在TypeScript中,数组值的数据类型为数组类型。
数组类型定义
TypeScript提供了以下两种方式来定义数组类型:
- 简便数组类型表示法。
- 泛型数组类型表示法。
以上两种数组类型定义方式仅在编码风格上有所区别,两者在功能上没有任何差别。
简便数组类型表示法
简便数组类型表示法借用了数组字面量的语法,通过在数组元素类型之后添加一对方括号“[]”
来定义数组类型。它的语法如下所示:
TElement[]
该语法中,TElement
代表数组元素的类型,方括号“[]”
代表数组类型。在TElement与“[]”之间不允许出现换行符号。
下例中,我们使用“number[]”
类型注解定义了常量digits的类型为number数组类型,它表示digits数组中元素的类型为number类型。示例如下:
const digits: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
如果数组中元素的类型为复合类型,则需要在数组元素类型上使用分组运算符,即小括号。
例如,下例中的red
数组既包含字符串元素也包含数字元素。因此,red数组元素的类型为string类型和number类型构成的联合类型,即“string | number”
。
在使用简便数组类型表示法时,必须先将联合类型放在分组运算符内,然后再在后面添加一对方括号。示例如下:
const red: (string | number)[] = ['f', f, 0, 0, 0, 0];
此例中,若在类型注解里没有使用分组运算符,则表示string类型和number[]类型的联合类型,即“string | (number[])”
。该类型与实际数组类型不兼容,因此将产生编译错误。示例如下:
const red: string | number[] = ['f', 'f', 0, 0, 0, 0];
// ~~~
// 编译错误
泛型数组类型表示法
泛型数组类型表示法是另一种表示数组类型的方法。顾名思义,泛型数组类型表示法就是使用泛型来表示数组类型。它的语法如下所示:
Array<TElement>
该语法中,Array代表数组类型;“<TElement>”
是类型参数的语法,其中TElement
代表数组元素的类型。
下例中,我们使用“Array<number>”
类型注解定义了常量digits的类型为number数组类型,它表示digits数组中元素的类型为number类型。示例如下:
const digits: Array<number> = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
在使用泛型数组类型表示法时,就算数组中元素的类型为复合类型也不需要使用分组运算符。我们还是以既包含字符串元素也包含数字元素的red
数组为例,示例如下:
const red: Array<string | number> = ['f', 'f', 0, 0, 0, 0];
此例中,我们不再需要对联合类型“string | number”
使用分组运算符。
两种方法比较
正如前文所讲,简便数组类型表示法和泛型数组类型表示法在功能上没有任何差别,两者只是在编程风格上有所差别。
在定义简单数组类型时,如数组元素为单一原始类型或类型引用,使用简便数组类型表示法更加清晰和简洁。示例如下:
let a: string[];
let b: HTMLButtonElement[];
如果数组元素是复杂类型,如对象类型和联合类型等,则可以选择使用泛型数组类型表示法。它也许能让代码看起来更加整洁一些。示例如下:
let a: Array<string | number>;
let b: Array<{ x: number; y: number }>;
总结起来,目前存在以下三种常见的编码风格供读者参考:
- 始终使用简便数组类型表示法。
- 始终使用泛型数组类型表示法。
- 当数组元素类型为单一原始类型或类型引用时,始终使用简便数组类型表示法;在其他情况下不做限制。
数组元素类型
在定义了数组类型之后,当访问数组元素时能够获得正确的元素类型信息。示例如下:
const digits: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const zero = digits[0];
// ~~~~
// number类型
此例中,虽然没有给常量zero添加类型注解,但是TypeScript编译器能够从数组类型中推断出zero的类型为number类型。
我们知道,当访问数组中不存在的元素时将返回undefined
值。TypeScript的类型系统无法推断出是否存在数组访问越界的情况,因此即使访问了不存在的数组元素,还是会得到声明的数组元素类型。示例如下:
const digits: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 没有编译错误
const out: number = digits[100];
只读数组
只读数组与常规数组的区别在于,只读数组仅允许程序读取数组元素而不允许修改数组元素。
TypeScript提供了以下三种方式来定义一个只读数组:
- 使用
“ReadonlyArray<T>”
内置类型。 - 使用
readonly
修饰符。 - 使用
“Readonly<T>”
工具类型。
以上三种定义只读数组的方式只是语法不同,它们在功能上没有任何差别。
ReadonlyArray
在TypeScript早期版本中,提供了“ReadonlyArray<T>”
类型专门用于定义只读数组。在该类型中,类型参数T表示数组元素的类型。示例如下:
const red: ReadonlyArray<number> = [255, 0, 0];
此例中,定义了只读数组red,该数组中元素的类型为number。
readonly
TypeScript 3.4版本中引入了一种新语法,使用readonly
修饰符能够定义只读数组。在定义只读数组时,将readonly修饰符置于数组类型之前即可。示例如下:
const red: readonly number[] = [255, 0, 0];
注意,readonly修饰符不允许与泛型数组类型表示法一起使用。示例如下:
const red: readonly Array<number> = [255, 0, 0];
// ~~~~~~~~
// 编译错误
Readonly
“Readonly<T>”
是TypeScript提供的一个内置工具类型,用于定义只读对象类型。该工具类型能够将类型参数T的所有属性转换为只读属性,它的定义如下所示:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
由于TypeScript 3.4支持了使用readonly修饰符来定义只读数组,所以从TypeScript 3.4开始可以使用“Readonly<T>”
工具类型来定义只读数组。示例如下:
const red: Readonly<number[]> = [255, 0, 0];
需要注意的是,类型参数T的值为数组类型
“number[]”
,而不是数组元素类型number。在这一点上,它与“ReadonlyArray<T>”
类型是有区别的。
注意事项
我们可以通过数组元素索引来访问只读数组元素,但是不能修改只读数组元素。示例如下:
const red: readonly number[] = [255, 0, 0];
red[0]; // 正确
red[0] = 0; // 编译错误
在只读数组上也不支持任何能够修改数组元素的方法,如push和pop方法等。示例如下:
const red: readonly number[] = [255, 0, 0];
red.push(0); // 编译错误
red.pop(); // 编译错误
在进行赋值操作时,允许将常规数组类型赋值给只读数组类型,但是不允许将只读数组类型赋值给常规数组类型。换句话说,不能通过赋值操作来放宽对只读数组的约束。示例如下:
const a: number[] = [0];
const ra: readonly number[] = [0];
const x: readonly number[] = a; // 正确
const y: number[] = ra; // 编译错误
酷客网相关文章:
评论前必须登录!
注册