- 引用
- 链接 👈 具名元组 GitHub TypeScript Issues:
Feature Request: Add labels to tuple elements
- 链接 👈 具名元组 GitHub TypeScript Issues:
- 元组(Tuple)
- 问:元组是啥?它和数组啥关系?
- 元组是一种特殊的类型
- 元组可以看作是具有固定长度和固定类型的数组
- 元组用于表示一个已知元素数量和类型的数组,各元素的类型并不必完全相同。
- js 的开发者对元组 Tuple 的概念可能比较陌生,毕竟在 js 中我们很少声明定长的数组。但使用元组确实能帮助你进一步提升数组结构的严谨性,包括基于位置的类型标注、避免出现越界访问等等。
- 当直接对元组类型的变量进行初始化或者赋值的时候,需要提供所有元组成员中指定的必填项,并且类型也要满足要求。
- 数组通常是用来约束同一类型的一组数据的集合
- 元组通常是用来约束不同类型的一组数据的集合,指定位置的成员需要满足约束
const arr1: string[] = ['a', 'b', 'c']
const arr2: [string, number, boolean] = ['a', 1, true]
- 数组的长度通常是不固定的,并且 ts 无法对越界访问抛出错误提示
- 元组的长度通常是固定的,如果出现越界访问的情况,会及时抛出错误
显式地越界访问:
const arr1: string[] = ['a', 'b', 'c']
const arr2: [string, string, string] = ['a', 'b', 'c']
arr1[3] // undefined
// error 长度为 "3" 的元组类型 "[string, string, string]" 在索引 "3" 处没有元素。ts(2493)
arr2[3]
隐式地越界访问:
const arr1: string[] = ['a', 'b', 'c']
const arr2: [string, string, string] = ['a', 'b', 'c']
const [x1, x2, x3, x4] = arr1;
// error 长度为 "3" 的元组类型 "[string, number, boolean]" 在索引 "3" 处没有元素。
const [a1, a2, a3, a4] = arr2;
- 可以给元组类型标识可选成员,语法是在类型后边儿加上问号
let arr:[string, number?]
const arr: [string, number?, boolean?] = ['a', 1, true]
type TupleLength = typeof arr.length
// type TupleLength = 1 | 2 | 3
// 使用 typeof 查询 arr.length 的类型
// 从结果 1 | 2 | 3 可知 ts 认为,arr 的长度可能是 1、2、3
// 当 "strictNullChecks": false 时的推断结果
// const arr: [string, number?, boolean?]
// 当 "strictNullChecks": true 时的推断结果
// const arr: [string, (number | undefined)?, (boolean | undefined)?]
- 在 TypeScript 4.0 中,TypeScript 增加了具名元组成员 (labeled tuple elements) 的功能。在之前的版本中,元组(tuple)只是一个类型的数组,例如
[string, number]
。但是这些类型没有描述性的标签,这使得在某些情况下可能难以理解元组的意图。 - 具名元组也支持可选元素和剩余元素
- 具名元组使得我们可以为元组中的元素打上类似属性的标签,增强代码的可读性,并不会改变元组的行为
type PersonInfo = [name: string, age: number, male?: boolean, ...otherInfos: any[]]
const printPerson = (person: PersonInfo) => {
console.log('name:', person[0])
console.log('age:', person[1])
console.log('male:', person[2])
console.log('otherInfos:', person.slice(3))
}
printPerson(['abc', 123, false, '23.08.22', '摸鱼学习 ts'])
// name: abc
// age: 123
// male: false
// otherInfos: [ '23.08.22', '摸鱼学习 ts' ]
这些标签不会在运行时存在,它们的作用仅仅是在程序中给予一些提示罢了。
- push
- 给指定成员赋值时,下标不能越界,但是直接 push 溢出是被允许的
- 对于元组类型而言,push 溢出实际上没啥意义,因为我们访问溢出的成员在 ts 中是会报错的
- push 新增的成员,类型必须是元组中每个类型的联合类型
// 声明一个元组类型
let tuple: [string, number];
tuple = ["abc", 123];
// ok
tuple.push('1', '2', 3, 4)
// '1', '2', 3, 4 都是 string | number 类型
// 类型“boolean”的参数不能赋给类型“string | number”的参数。
tuple.push(true)