本文介绍了从元组类型中删除所有可选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我想要将具有[1, 2, 3?, 4?]等可选项的元组转换为仅包含必需项的数组->;[1, 2]

我想出来的如下所示,它变成了Never All Option Items,我被困在这里。

type OnlyReq <L extends any []> = {
  [K in keyof L]-?: L [K] extends Required <L> [K]  ? L [K] : never
}

type Found = OnlyReq <[1, 2, 3?, 4?]> // [1, 2, never, never]

playground

推荐答案

我在这里的方法是编写一个recursive conditional type(实际上是tail recursive,因此它将适用于TS4.5+中相当长的元组),它遍历tuple,直到它发现其余的都是可选的

请注意,optional elements in tuple types后面不能跟必需的元素;也就是说,像[1, 2?, 3]这样的元素是不可能的。因此,如果元组具有任何必需元素,则必须特别需要第一个元素。

以下是一个实现:

type OnlyReq<T extends any[], U extends any[] = []> = Partial<T> extends T ? U :
  T extends [infer F, ...infer R] ? OnlyReq<R, [...U, F]> : U

我们在类型参数U(以空元组[]开始)中累加结果,因此一旦我们决定停止迭代,就返回U

检查Partial<T> extends T使用the Partial<T> utility type得到输入元组的全可选版本。一般来说,T extends Partial<T>是真的,但Partial<T> extends T不是,除非T已经与Partial<T>相同.换句话说,Partial<T> extends T当且仅当T是全可选的。

如果元组T是全可选的,则返回U。另外,如果T为空,我们将返回U(如果T不能拆分成第一个元素F和一个剩余的元组R,就会发生这种情况)。如果T有第一个元素F,那么我们知道它是必需的(否则T将是全可选的),我们只需将其推到U元组的末尾,以便递归调用元组的其余部分R


让我们看看它是否有效:

type Found = OnlyReq<[1, 2, 3?, 4?]>
// type Found = [1, 2]

看起来不错。

还请注意,rest elements in tuple types在同一测试中也被认为是可选的,因此它们也应该被去除:

type StripRest = OnlyReq<[string, boolean?, ...number[]]> 
// type StripRest = [string]

实际上,非元组数组类型(Foo[])等同于仅由一个rest元素([...Foo[]])组成的元组,因此将被转换为空元组,这可能是您想要的,也可能不是:

type Hmm = OnlyReq<number[]>
// type Hmm = []

我认为"leading" or "middle" rest elements in tuple types超出了这里的范围,因为它们会做奇怪的事情,而您没有问到它们(我希望不会出现,因为操作这种类型很烦人):

type What = OnlyReq<[...string[], number]>
// type What = []
type AlsoWhat = OnlyReq<[string, ...boolean[], number]>
//type AlsoWhat = [string]

Playground link to code

这篇关于从元组类型中删除所有可选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-02 15:24