我有一个数据集合,看起来像这样:
interface Item {
name: "one" | "two";
data: string;
}
const namedItems: Item[] = [
{
name: "one",
data: "some data one",
},
{
name: "two",
data: "some data two",
},
];
每个项都有一个名称,值可以是“一”或“二”。
然后运行数组查找:
const getData = (query: "one" | "two") =>
namedItems.find((item): boolean => query === item.name).data;
抛出一个类型脚本错误“Object is possibly 'undefined'”。这似乎是因为find可能找不到某些东西,但在我的示例中,只允许查找“one”或“two”,这将始终返回一个结果。
我如何让typescript知道它总是会在find中返回结果?
8条答案
按热度按时间dnph8jn41#
您遇到这种情况的原因是
Array.prototype.find
的类型签名:如您所见,它总是返回
T | undefined
,这很有意义,因为定义为Item[]
的集合可以包含任意数量的项,包括0。在您的示例中,集合是完整的,但在类型级别上,它与[{ name: "one", data: "some data one" }]
甚至[]
没有区别。为了以类型安全的方式访问
item.data
,TypeScript将要求您仔细检查是否确实找到了结果。由于从长远来看这会变得很麻烦,您可能会发现为这种场景创建一个帮助器函数是很有用的。
用法:
ddarikpa2#
如果你绝对肯定你总是会得到一个匹配,那么你可以告诉TS:
使用项目类型Assert:
第一个月
或非空Assert后缀:
const getData = (query: 'one' | 'two') => namedItems.find((item) => query === item.name)!.data;
n53p2ov03#
使用筛选器而不是查找:
版本1:
版本2:
不知道我是否理解你是否只想要一个结果...如果是这样的话
3phpmpom4#
**选项1:**最简单的破解方法是使用非空Assert操作符:
**选项2:**在Typescript 3.7中,这可以通过Assert函数轻松实现:
A行中的Assert函数
assert()
影响了B行中item
的静态类型,使其成为Item
。在Node.js中,可以通过the built-in module使用
assert()
函数:在浏览器环境中,需要自己声明它。
例如,在项目的utilities/文件夹中:
cidc1ykv5#
我如何让typescript知道它总是会在find中返回结果?
最简单、最懒惰、最丑陋和最容易出错的解决方案是使用非空Assert操作符:
第一个月
这是一种告诉typescript该值将始终被定义的方式,但是话又说回来,如果要覆盖它,为什么还要使用typescript呢?您应该"真正"地防范可能出现的未定义值,因为代码可能在将来更改,错误也可能发生。因此,使用之前推荐的任何解决方案,或者我的解决方案:
空合并运算符(??)是一种逻辑运算符,当左侧操作数为空或未定义时,它返回右侧操作数,否则返回左侧操作数。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator
如果你想要一个默认值,你可以在
??
-运算符的右边添加任何你想要的值,如果你不想要,你可以做一个错误检查:if(!getData())
iyzzxitl6#
Array.find()
可能不成功,并可能返回undefined
。由于Typescript不知道
namedItems
数组在运行时不为空(在本例中肯定会失败),因此您无法对其执行任何操作。但是,您可以使用不同的方法来提取
data
字段(仅当找到项时),例如,您可以将结果 Package 在数组中,然后Mapif并提取它:roqulrg37#
最简洁的代码可能是这样的:使用可选的链接运算符(?.)并键入Item|任何
2izufjch8#
将find的结果设置为any类型的变量|允许其接受空结果的项目:
See CodePen