科技速递|TypeScript 4.0发布,新增可变参数元组类型等( 二 )


可变参数元组类型想象JavaScript中的一个函数 , 该函数concat采用两个数组或元组类型并将它们连接在一起以创建一个新数组 。
function concat(arr1, arr2) {return [...arr1, ...arr2];}还有tail , 它接受一个数组或元组 , 并返回除第一个元素外的所有元素 。
function tail(arg) {const [_, ...result] = arg;return result}如何在TypeScript中键入其中一个?
对于concat , 在较旧版本的语言中唯一可以做的就是编写重载 。
function concat(arr1: [], arr2: []): [];function concat(arr1: [A], arr2: []): [A];function concat(arr1: [A, B], arr2: []): [A, B];function concat(arr1: [A, B, C], arr2: []): [A, B, C];function concat(arr1: [A, B, C, D], arr2: []): [A, B, C, D];function concat(arr1: [A, B, C, D, E], arr2: []): [A, B, C, D, E];function concat(arr1: [A, B, C, D, E, F], arr2: []): [A, B, C, D, E, F];)
第二个数组始终为空时的七个重载 。 arr2有一个参数的情况:
function concat(arr1: [], arr2: [A2]): [A2];function concat(arr1: [A1], arr2: [A2]): [A1, A2];function concat(arr1: [A1, B1], arr2: [A2]): [A1, B1, A2];function concat(arr1: [A1, B1, C1], arr2: [A2]): [A1, B1, C1, A2];function concat(arr1: [A1, B1, C1, D1], arr2: [A2]): [A1, B1, C1, D1, A2];function concat(arr1: [A1, B1, C1, D1, E1], arr2: [A2]): [A1, B1, C1, D1, E1, A2];function concat(arr1: [A1, B1, C1, D1, E1, F1], arr2: [A2]): [A1, B1, C1, D1, E1, F1, A2];很明显 , 这已经变得不合理了 。 不幸的是 , 键入像这样的函数也会遇到tail同样的问题 。
还有另外一种情况 , 被称为"一千个重载死亡" , 它甚至不能解决一般问题 。 它只为想写的重载给出正确的类型 。 如果想做一个包罗万象的案例 , 则需要像下面这样的重载:
function concat(arr1: T[], arr2: U[]): Array;但是 , 使用元组时 , 该签名不会对输入的长度或元素的顺序进行任何编码 。
TypeScript 4.0带来了两个基本改善 , 并在推理方面进行了改进 , 使键入这些内容成为可能 。
第一个变化是元组类型语法中的传播现在可以通用 。 这样即使不知道要操作的实际类型 , 也可以表示元组和数组的高阶操作 。 当在这些元组类型中实例化通用扩展时(或用实型替换) , 它们可以产生其他数组和元组类型集 。
例如 , 可以在TS 4.0中键入像这样的函数tail , 而不会出现"一千个重载死亡"的问题 。
function tail(arr: readonly [any, ...T]) {const [_ignored, ...rest] = arr;return rest;}const myTuple = [1, 2, 3, 4] as const;const myArray = ["hello", "world"];// type [2, 3, 4]const r1 = tail(myTuple);// type [2, 3, 4, ...string[]]const r2 = tail([...myTuple, ...myArray] as const);第二个变化是 , 其余元素可以出现在元组中的任何位置 , 而不仅仅是在结尾 。
type Strings = [string, string];type Numbers = [number, number];// [string, string, number, number, boolean]type StrStrNumNumBool = [...Strings, ...Numbers, boolean];之前 , TypeScript会发出如下错误:
A rest element must be last in a tuple type.TypeScript 4.0可以放宽此限制 。
请注意 , 在没有已知长度的类型的情况下 , 结果类型也将变得不受限制 , 并且所有以下所有元素都将成为结果其余元素类型 。
type Strings = [string, string];type Numbers = number[]// [string, string, ...Array


推荐阅读