示例1
const myNumber = _.sample([1, 2, 3]);
// Expected type: number
// Actual type: number
示例2
const arr = [1, 2, 3]
const myNumber = _.sample(arr);
// Expected type: number
// Actual type: number | undefined
为什么 Typescript 在第二种情况下给出类型
number | undefined
,而不是第一种情况?
发生这种情况是因为在一种情况下数组的长度是已知的,而在另一种情况下则不是。如果长度可能为 0,则可能的输出为 undefined。
当您执行
const arr = [1, 2, 3]
时,数组的类型为 number[]
。这意味着它是一个可以增长和缩小的数字数组。你和我可以看到它在下一行之前不会缩小,但类型信息不包含该知识。因此,当它传递到样本中时,类型表示可能的结果是未定义。
当您在完全相同的位置创建和使用数组时(如
_.sample([1, 2, 3]);
所示),TypeScript 能够采用更严格的类型,因为它知道如何使用它。推断类型为[number, number, number]
,即长度为3的元组,因此肯定会返回一个元素。
如果您想在数组位于单独的行上时实现此目的,则需要告诉打字稿您想要在
arr
上使用更严格的类型。最简单的方法是使用 as const
,它可以让你告诉打字稿你不会更改这个数组:
const arr = [1, 2, 3] as const; // readonly [number, number, number]
const myNumber = _.sample(arr); // number
您可以在此处查看
sample
的类型定义: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/lodash/common/collection.d.ts#L1641 。元组情况由这种类型处理:
sample<T>(collection: readonly [T, ...T[]]): T;
数组情况由这种类型处理:
sample<T>(collection: Dictionary<T> | NumericDictionary<T> | null | undefined): T | undefined;