- 引用
- 链接 👈 具名元组 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];// oktuple.push('1', '2', 3, 4)// '1', '2', 3, 4 都是 string | number 类型// 类型“boolean”的参数不能赋给类型“string | number”的参数。tuple.push(true)
