前言
在平时需求中我们经常会遇到定义定长数组类型的需求
比如一个 9x9 的棋盘 model:
let board = [
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
];
复制代码
我们知道 typescript 是支持设定一个数组类型的,那有没有办法设置一个定长的数组类型呢?
本体
首先我们来看一个简单的例子,定义一个 iMArray 的数组并把它的类型置为 number[]
let iMArray: number[] = [0, 1];
复制代码
这是这种类型有个弊端,那就是我们并没法限制数组的长度:
iMArray.length = 3;
iMArray[3] = 1;
复制代码
其中一种解决方式是使用元组来定义类型
let iMArray: [number, number] = [0, 1];
复制代码
可以看到当我想对超出限定范围下标的数组元素进行赋值时, typescript 会给我们提示异常.
// boom
iMArray[3] = 1;
复制代码
可是假如我们想定义一个长度限制在50的数组呢?难不成要写50遍 number?
不,解决办法还是有的,在 Typescript 3.0 中引入一个新的特性叫元组展开
假如我们想定义一个长度为 50 的数组, 我们只要这样写:
type Tuple50<TItem> = [TItem, ...TItem[]] & { length: 50 };
let iMArray: Tuple50<number> = [0,...,50];
复制代码
可以看到,结合元组展开以及交叉类型,我们成功定义了一个长度为50,数组元素为 number 的数组.
回到前言提到的那个棋盘类,我们就可以这样定义一个9x9的棋盘类型了.
type Tuple9<TItem> = [TItem, ...TItem[]] & { length: 9 };
type TypeBoard<T> = Tuple9<Tuple9<T>>;
let board: TypeBoard<number> = [
[0, ..., 9],
...
[0, ..., 9],
]
复制代码
最后给一个封装好的 Tuple 类
type Tuple<TItem, TLength extends number> = [TItem, ...TItem[]] & { length: TLength };
复制代码