1. 引用
      1. 链接 👈 具名元组 GitHub TypeScript Issues:Feature Request: Add labels to tuple elements
    2. 元组(Tuple)
    3. 问:元组是啥?它和数组啥关系?
      1. 元组是一种特殊的类型
      2. 元组可以看作是具有固定长度和固定类型的数组
    4. 元组用于表示一个已知元素数量和类型的数组,各元素的类型并不必完全相同。
    5. js 的开发者对元组 Tuple 的概念可能比较陌生,毕竟在 js 中我们很少声明定长的数组。但使用元组确实能帮助你进一步提升数组结构的严谨性,包括基于位置的类型标注、避免出现越界访问等等。
    6. 当直接对元组类型的变量进行初始化或者赋值的时候,需要提供所有元组成员中指定的必填项,并且类型也要满足要求。
    7. 数组通常是用来约束同一类型的一组数据的集合
    8. 元组通常是用来约束不同类型的一组数据的集合,指定位置的成员需要满足约束
    1. const arr1: string[] = ['a', 'b', 'c']
    2. const arr2: [string, number, boolean] = ['a', 1, true]
    1. 数组的长度通常是不固定的,并且 ts 无法对越界访问抛出错误提示
    2. 元组的长度通常是固定的,如果出现越界访问的情况,会及时抛出错误

    显式地越界访问:

    1. const arr1: string[] = ['a', 'b', 'c']
    2. const arr2: [string, string, string] = ['a', 'b', 'c']
    3. arr1[3] // undefined
    4. // error 长度为 "3" 的元组类型 "[string, string, string]" 在索引 "3" 处没有元素。ts(2493)
    5. arr2[3]

    隐式地越界访问:

    1. const arr1: string[] = ['a', 'b', 'c']
    2. const arr2: [string, string, string] = ['a', 'b', 'c']
    3. const [x1, x2, x3, x4] = arr1;
    4. // error 长度为 "3" 的元组类型 "[string, number, boolean]" 在索引 "3" 处没有元素。
    5. const [a1, a2, a3, a4] = arr2;
    1. 可以给元组类型标识可选成员,语法是在类型后边儿加上问号 let arr:[string, number?]
    1. const arr: [string, number?, boolean?] = ['a', 1, true]
    2. type TupleLength = typeof arr.length
    3. // type TupleLength = 1 | 2 | 3
    4. // 使用 typeof 查询 arr.length 的类型
    5. // 从结果 1 | 2 | 3 可知 ts 认为,arr 的长度可能是 1、2、3
    6. // 当 "strictNullChecks": false 时的推断结果
    7. // const arr: [string, number?, boolean?]
    8. // 当 "strictNullChecks": true 时的推断结果
    9. // const arr: [string, (number | undefined)?, (boolean | undefined)?]
    1. 在 TypeScript 4.0 中,TypeScript 增加了具名元组成员 (labeled tuple elements) 的功能。在之前的版本中,元组(tuple)只是一个类型的数组,例如 [string, number]。但是这些类型没有描述性的标签,这使得在某些情况下可能难以理解元组的意图。
    2. 具名元组也支持可选元素和剩余元素
    3. 具名元组使得我们可以为元组中的元素打上类似属性的标签,增强代码的可读性,并不会改变元组的行为
    1. type PersonInfo = [name: string, age: number, male?: boolean, ...otherInfos: any[]]
    2. const printPerson = (person: PersonInfo) => {
    3. console.log('name:', person[0])
    4. console.log('age:', person[1])
    5. console.log('male:', person[2])
    6. console.log('otherInfos:', person.slice(3))
    7. }
    8. printPerson(['abc', 123, false, '23.08.22', '摸鱼学习 ts'])
    9. // name: abc
    10. // age: 123
    11. // male: false
    12. // otherInfos: [ '23.08.22', '摸鱼学习 ts' ]

    这些标签不会在运行时存在,它们的作用仅仅是在程序中给予一些提示罢了。

    1. push
      1. 给指定成员赋值时,下标不能越界,但是直接 push 溢出是被允许的
      2. 对于元组类型而言,push 溢出实际上没啥意义,因为我们访问溢出的成员在 ts 中是会报错的
      3. push 新增的成员,类型必须是元组中每个类型的联合类型
    1. // 声明一个元组类型
    2. let tuple: [string, number];
    3. tuple = ["abc", 123];
    4. // ok
    5. tuple.push('1', '2', 3, 4)
    6. // '1', '2', 3, 4 都是 string | number 类型
    7. // 类型“boolean”的参数不能赋给类型“string | number”的参数。
    8. tuple.push(true)