【问题标题】:Is it possible to define a non empty array type in Typescript?是否可以在 Typescript 中定义非空数组类型?
【发布时间】:2019-09-24 03:26:14
【问题描述】:

我有一个我知道永远不会为空的数字列表。是否可以在 Typescript 中定义一个从不为空的数组?

我知道像 [ number, number ] 这样的元组是可能的,但这不起作用,因为我的数组可以是任何大小。

我猜我要找的是NonEmptyArray<number> 类型。

它存在吗? :)

【问题讨论】:

  • 你的意思是需要的物品吗?
  • 似乎应该可以使用Exclude,但尽管type NonEmptyNumberArray = Exclude<number[], []>; 解析,结果只是number[] 的别名。
  • 我的意思是输入MyArray = [ number, number ]。只针对 n 个项目,而不是两个。

标签: typescript


【解决方案1】:

允许您仅检查 array.length > 0 以防范空数组的功能请求 microsoft/TypeScript#38000 因过于复杂而被拒绝。本质上,您通常不能简单地在 TypeScript 中检查 length 以使编译器相信给定数字键的属性的可用性。

你可以像这样定义一个非空数组类型:

type NonEmptyArray<T> = [T, ...T[]];

const okay: NonEmptyArray<number> = [1, 2];
const alsoOkay: NonEmptyArray<number> = [1];
const err: NonEmptyArray<number> = []; // error!

这是由于在 TS 3.0 中添加了对 rest elements in tuple types 的支持。我不确定你的用例是什么......不过,使用这种类型可能比你想象的更烦人:

function needNonEmpty(arr: NonEmptyArray<number>) {}
function needEmpty(arr: []) {}

declare const bar: number[];
needNonEmpty(bar); // error, as expected

if (bar.length > 0) {
    needNonEmpty(bar); // ugh, still error!
}

如果你想让length 检查起作用,你需要使用类似用户定义的类型保护函数,但使用起来还是很烦人:

function isNonEmptyArray<T>(arr: T[]): arr is NonEmptyArray<T> {
    return arr.length > 0;
}

if (isNonEmptyArray(bar)) {
    needNonEmpty(bar); // okay
} else {
    needEmpty(bar); // error!! urgh, do you care?        
} 

无论如何希望这会有所帮助。祝你好运!

【讨论】:

  • 是的,基本上在调用之前使用类型保护。必须是 OP 想要的,以便编译器可以强制执行。真的很酷很奇怪,我希望我永远不需要这个:)
  • 我的用例是这样的:当在 T 列表上使用 head() 和 last() 等函数时,它们默认返回 T |不明确的。这意味着我必须进行检查,或者当我知道数组永远不会为空时,我必须进行类型转换。如果我有一个 NonEmptyArray 我的 head 和 last 函数可以总是返回 T 并且不需要检查也不需要类型转换。
  • 这很好,但您可能仍需要在 调用 head()last() 而不是在调用期间或之后进行这些检查/断言。
  • 即使使用了这些类型保护,pop() 或 shift() 的 Array 返回类型也不会改变,因此您要么必须转换结果,要么使用自己的函数如上例所示。任何内置的数组方法都不会得到更好的推断返回类型。
【解决方案2】:

我也对此感到疑惑,并想出了一个不同的解决方案:

type NonEmptyArray<T> = T[] & { 0: T };

【讨论】:

  • 这种风格的另一种选择是type NonEmpty&lt;T&gt; = T extends Array&lt;infer U&gt; ? U[] &amp; {'0': U} : never;。用法:const x: NonEmpty&lt;string[]&gt; = ["myString"];。这将 NonEmpty 部分与 Array 部分分开。
  • 这不包括第一个成员未定义但其他成员有值的数组。
  • @jsejcksn 你能举个例子吗?
  • 我看到 arr 在这种情况下具有 NonEmptyArray&lt;number | undefined&gt; 类型。取决于你如何定义你真正想要使用的类型。
  • 这本质上是the definition 使用的fp-ts
猜你喜欢
  • 2020-08-24
  • 2017-09-14
  • 2012-08-11
  • 2018-01-21
  • 2018-01-03
  • 2016-07-22
  • 1970-01-01
  • 2018-03-01
  • 2022-01-25
相关资源
最近更新 更多