根据数组的长度缩小第一个数组元素的类型?

问题描述 投票:0回答:1

我正在处理一个数组,如果数组的长度为 1,则第一个元素的类型是已知的,并且可以是两种类型之一,否则;即类似以下内容:

type NarrowableArray<TKnown, TGenereal> = [TKnown] | [TGeneral, TGeneral, ...TGeneral[]] type Foo = number | number[] let a: NarrowableArray<number, Foo> = Math.random() > 0.5 ? [3] : [3,4,5] if (a.length === 1) { a console.log(a[0] + 2) //Error > TS can't tell `a[0]` has type 'number'. }
这是预期的吗? 

有没有办法让函数声明中的类型缩小工作相同?

arrays typescript tuples type-narrowing
1个回答
0
投票
问题是

开放式元组类型

length属性是number
,如
microsoft/TypeScript#24897中所述; TypeScript 没有准确的 range types(如 microsoft/TypeScript#15480 中所要求的)来表达“除 1
 之外的任何数字”或 
{length: WholeNumber & GreaterThan<1>}

所以不幸的是,仅仅检查

length

1
属性将无法区分
union,因为两个union成员都有一个length
1
可分配给它。

还有其他更自然地直接与元组一起工作的缩小方法,但是如果您想自己执行长度检查,您可能需要重构为

用户定义的类型保护函数,形式为:

function hasLengthOne(x: any[]): x is [any] { return x.length === 1; }
然后调用它而不是直接检查长度:

function aFunction(a: NarrowableArray<number, Foo>) { if (hasLengthOne(a)) { a // (parameter) a: [number] console.log(a[0] + 2); // okay } else { a // (parameter) a: [Foo, Foo, ...Foo[]] } }
之所以有效,是因为编译器能够通过 

NarrowableArray<number, Foo>

 过滤 
[any]
;我们正在完全规避
length
问题。

游乐场代码链接

© www.soinside.com 2019 - 2024. All rights reserved.