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



还有tail , 它接受一个数组或元组 , 并返回除第一个元素外的所有元素 。
如何在TypeScript中键入其中一个?
对于concat , 在较旧版本的语言中唯一可以做的就是编写重载 。
第二个数组始终为空时的七个重载 。 arr2有一个参数的情况:
很明显 , 这已经变得不合理了 。 不幸的是 , 键入像这样的函数也会遇到tail同样的问题 。
还有另外一种情况 , 被称为"一千个重载死亡" , 它甚至不能解决一般问题 。 它只为想写的重载给出正确的类型 。 如果想做一个包罗万象的案例 , 则需要像下面这样的重载:
但是 , 使用元组时 , 该签名不会对输入的长度或元素的顺序进行任何编码 。
TypeScript 4.0带来了两个基本改善 , 并在推理方面进行了改进 , 使键入这些内容成为可能 。
第一个变化是元组类型语法中的传播现在可以通用 。 这样即使不知道要操作的实际类型 , 也可以表示元组和数组的高阶操作 。 当在这些元组类型中实例化通用扩展时(或用实型替换) , 它们可以产生其他数组和元组类型集 。
例如 , 可以在TS 4.0中键入像这样的函数tail , 而不会出现"一千个重载死亡"的问题 。
第二个变化是 , 其余元素可以出现在元组中的任何位置 , 而不仅仅是在结尾 。
之前 , TypeScript会发出如下错误:

A rest element must be last in a tuple type.
TypeScript 4.0可以放宽此限制 。
请注意 , 在没有已知长度的类型的情况下 , 结果类型也将变得不受限制 , 并且所有以下所有元素都将成为结果其余元素类型 。
通过将这两种功能结合在一起 , 就可以很便捷的编写一个类型正确的签名
尽管一个签名仍然有些冗长 , 但这只是一个签名 , 不必重复 , 它可以在所有数组和元组上提供可预测的行为 。
功能本身很棒 , 但在更复杂的场景中也很有用 。 例如 , 函数partialCall的部分应用名为的参数 。 partialCall带有一个函数f以及几个初始的期望参数 , 返回一个新函数 , 该函数接受f仍需要的任何其他参数 , 并f在接收到它们时进行调用 。
TS 4.0改进了rest参数和rest tuple元素的推断过程 , 使其"正常工作":
partialCall了解其初始可以使用和不能使用的参数 , 并返回可以接受和拒绝的函数 。
可变参数元组类型启用了许多新的令人兴奋的模式 , 尤其是在函数组成方面 , 可以利用它来做更好的工作 , 以检查JavaScript的内置bind方法的类型 。
元组元素标签

改善元组类型和参数列表非常重要 , 围绕常见的JavaScript习惯用法进行强类型验证 。 实际上只是对参数列表进行切片和切块并将它们传递给其他函数 。 可以使用元组类型作rest参数的想法很有意义 。
例如 , 以下使用元组类型作为参数的函数
差异有:可读性 。 在第一个示例中 , 没有第一个和第二个元素的参数名称 。 尽管这些对类型检查没有影响 , 但元组位置上缺少标签会使其更难使用 , 难以传达意图 。
这就是为什么要在TypeScript 4.0中 , 元组类型需要提供标签了 。
为了加深参数列表和元组类型之间的联系 , 其余元素和可选元素的语法与参数列表的语法相同 。
使用带标签的元组时有一些规则 。 例如 , 当标记一个元组元素时 , 还必须标记该元组中的所有其他元素 。
值得注意的是 , 标签不需要在解构时以不同的方式命名变量 。 它们纯粹是那里的文档和工具 。
总的来说 , 带标签的元组在利用元组和参数列表周围的模式以及以类型安全的方式实现重载时很方便 。 实际上 , TypeScript的编辑器支持会在可能的情况下尝试将它们显示为重载 。
构造函数的类属性推断
当noImplicitAny启用时 , TypeScript 4.0可以使用控制流分析来确定类中的属性类型 。


推荐阅读