我有一个变量userBalances
,它是一个从一开始就拥有多个属性的对象。但是,稍后将分配一个属性,称为categories
。
发生这种情况的函数需要返回userBalances
,并将categories
属性返回给它。
// ... stuff before here
userBalances = userBalances.map((token) => {
return {
...props,
categories: ['a', 'b'],
};
});
return userBalances // <- TS linter saying that `categories` is missing
但是上面的代码不起作用,因为它说categories
丢失了。当我将代码修改为以下内容时:
// ... stuff before here
return userBalances.map((token) => {
return {
...props,
categories: ['a', 'b'],
};
}); // fine!
它工作正常。我不明白为什么会这样
编辑:用户余额在该函数的前面声明如下:
// an API result with an array of objects having all properties apart from `categories`
let userBalances = results.filter(({ balance }) => balance.gt(0));
1条答案
按热度按时间olmpazwi1#
我猜你的意思是你有这样的东西:
Playground链接
问题是,尽管您已经向
userBalances
中的元素添加了一个新属性,但userBalances
的 type 并没有改变,它仍然是{a: number}[]
(在上面)。在运行时,对象确实有TypeScript不知道的额外属性。当你执行
return
版本时,它不会发生,因为(我猜)你已经允许TypeScript从return
语句中推断返回类型,而不是在函数定义上提供特定的类型。通常的做法是赋值给一个新的变量,允许TypeScript推断其类型(就像
return
一样):Playground链接
在一条评论中,你问:
谢谢你的回答,我的问题。然而,我仍然不明白为什么TS不能看到我重新分配了新的属性。我想你是想通过这句话向我解释:
在运行时,对象确实有TypeScript不知道的额外属性
......但你能再详细一点吗?
我不认为TypeScript * 改变 * 现有变量的类型,当你给它一个新的值。(我不能肯定地说,但我不认为我遇到过它这样做。)它将narrow联合类型变量的上下文类型,但您在上面寻找的是TypeScript更改
userBalances
的类型,以在数组元素上包含b
属性,作为赋值的结果。据我所知,TypeScript并没有这样做。如果你愿意,你可以直接告诉编译器类型已经改变了,通过某种类型的保护(可能是类型 predicate 函数)或Assert函数。下面是一个使用Assert函数的例子:
Playground链接
我不建议这样做,因为这很不寻常(至少在我的经验中是这样),但是这种显式的语句告诉编译器
userBalances
的类型已经改变是可能的。我建议使用一个新的具有推断类型的变量。它也不那么麻烦(不需要Assert函数)。