我从以下代码中收到打字错误。据推测includes()
方法
p.id
是数字时,期望参数'never'。有人知道如何解决这个问题吗?
export interface IProductPrice {
id: number;
}
const [productPrices, setProductPrices] = useState<IProductPrice[]>([]);
const [selectedProductIds, setSelectedProductIds] = useState<string[] | number[]>([]);
const deleteSelectedProducts = (): void => {
setProductPrices(productPrices.filter((p): boolean => !selectedProductIds.includes(p.id)));
setSelectedProductIds([]);
};
答案 0 :(得分:7)
当您拥有不同类型的数组的并集时,就无法在它们上调用方法。
您有string[] | number[]
,因此.filter
是:
((filterFunc: (x: string) => boolean) => string[])
| ((filterFunc: (x: number) => boolean) => number[])
当TS组合这些签名时,它将把两个filterFunc
签名结合在一起:
((x: number) => boolean)
| ((x: string) => boolean)
这有点不直观,但这简化为(x: number & string) => boolean
。因为如果您有一个使用X的函数或一个使用Y的函数,那么传递的唯一安全的事情就是X
和Y
或X & Y
两者。
number & string
是不可能的类型,它“简化”为never
。因此,为什么签名是(x: never) => boolean
。
理想情况下,您只会使用string[]
或number[]
,而不能同时使用两者。 (仅看代码,为什么id
只能是数字,而“选定的产品ID”也可以是字符串,这有点奇怪)
但是,如果您确实需要同时支持字符串和数字,那么这里最简单的解决方法是使用Array<string | number>
而不是string[] | number[]
:单个数组类型不存在尝试合并在一起的问题两个.filter
签名。
您可以将状态更改为该类型:
const [selectedProductIds, setSelectedProductIds] = useState<Array<string | number>>([]);
这很简单,但是有一个缺点,那就是它允许混合的字符串和数字数组,这可能是不希望的。 (例如setSelectProductIds(['0', 1, '2'])
如果没有,则可以暂时强制转换为Array<string | number>
,进行过滤,然后强制转换为string[] | number[]
。这不是超级干净,但应该安全:
setProductPrices(
(productPrices as Array<string | number>).filter((p): boolean => !selectedProductIds.includes(p.id)) as (string[] | number[])
);
答案 1 :(得分:2)
为您的useState而不是
const [selectedProductIds, setSelectedProductIds] = useState<string[] | number[]>([]);
你能尝试
const [selectedProductIds, setSelectedProductIds] = useState< (string|number)[]>([]);
相反?
这是因为在将selectedProductIds
设置为字符串数组的地方可能缺少一些代码。在您的代码中,您已严格将其定义为1个数组,而不是另一个。也许上述更改可以解决此问题。请确认。