Ts 内置类型之 Tuple

540 阅读3分钟

Tuple 类型

Tuple Type(中文翻译:元组类型),可以认为是一个有顺序的数组类型。有以下特点:

  1. 可以明确知道包含了多少元素(这里的元素是类型)
  2. 可以明确知道每个类型所在的位置
  3. 长度固定,元组类型的变量需要为每一个位置定义对应类型的值

举例说明

type StringNumberPair = [string, number];

上述类型 StringNumberPair 定义了一个元组类型,包含了stringnumber 两种类型元素,元祖长度为 2,其中第一个元素类型是 string, 第二个元素类型是 number

下面我们结合几个例子来深入了解 Tuple Type

Tuple Type 的一般使用方式

type StringNumberPair = [string, number];

// 数组元素长度不满足 StringNumberPair 类型要求时
let testTupleTypeNoneEles: StringNumberPair = []; // Type '[]' is not assignable to type 'StringNumberPair'. Source has 0 element(s) but target requires 2

let testTupleTypeLessEles: StringNumberPair = ['1']; // Type '[string]' is not assignable to type 'StringNumberPair'. Source has 1 element(s) but target requires 2

let testTupleTypeMoreEls: StringNumberPair = ['1', 2, 3]; // Type '[string, number, number]' is not assignable to type 'StringNumberPair'. Source has 3 element(s) but target allows only 2

// 数组元素类型不匹配 StringNumberPair 类型要求时

let testTupleTypeUnMatchTypes: StringNumberPair = ['1', '2']; // Type 'string' is not assignable to type 'number'


// 数组元素符合 StringNumberPair 类型要求时
let testTupleTypeMatched: StringNumberPair = ['1', 2]; // ok

上面的例子测试了 Tuple Type 的变量在 元素个数不符元素类型不符 两种情况下的表现,可以看出 Tuple Type 的表现符合我们上面描述的特点。有兴趣的可以在线试下

Immutable Tuple Type (不可变元组)

不可变元组的意思是元组类型的变量内的元素值是不可变的,也就是不可再 增加元素删除元素修改元素值

具体实现方式有两种:

  1. 在 Tuple Type 字面量 前加 readonly 关键字。注意,不能加在类型 变量名 前。

语法如下:
type tupleTypeDemmo = readonly [string, number];

  1. 只要给数组类型的变量(注意:不是类型)后加 const 断言。就可以将该变量的类型看作是 readonly Tuple Type

举例:

let demo = [{
    item: {
        name: 'guoshi'
    }
}, 2] as const;

// error: Cannot assign to 'name' because it is a read-only property
demo[0].item.name = 1;

// error: Property 'push' does not exist on type 'readonly [{ readonly item: { readonly name: "guoshi"; }; }, 2]'
demo.push(2);

// error: Property 'splice' does not exist on type 'readonly [{ readonly item: { readonly name: "guoshi"; }; }, 2]'
demo.splice(0, 1);

// error: Property 'pop' does not exist on type 'readonly [{ readonly item: { readonly name: "guoshi"; }; }, 2]'
demo.pop();

// error: Property 'unshift' does not exist on type 'readonly [{ readonly item: { readonly name: "guoshi"; }; }, 2]'
demo.unshift();

可以看到,当类型是不可变元组时,元素不可变更,即使元素是多层次的引用类型,同样有效。 这对需要保持复杂数据不可变的场景是很有效的 在线地址

结合多个元组类型生成新的元组

方法很简单,ts 同样支持数组解构语法

type tupleFirst = [number];
type typleSecond = [string];
type intersectionTuple = [...tupleFirst, ...typleSecond]; // [number, string]

练习题:实现 TupleToObject

题目(原题目地址) :

const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const

type result = TupleToObject<typeof tuple> // expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}

答案