'number'类型的参数不能分配给array.includes()中'never'类型的参数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了'number'类型的参数不能分配给array.includes()中'never'类型的参数相关的知识,希望对你有一定的参考价值。
我从以下代码中收到打字错误。据推测includes()
方法p.id
是数字时,期望参数为“从不”。有人知道如何解决此问题吗?
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([]);
};
为您的useState代替
const [selectedProductIds, setSelectedProductIds] = useState<string[] | number[]>([]);
您可以尝试
const [selectedProductIds, setSelectedProductIds] = useState< (string|number)[]>([]);
代替?
这是因为可能在将selectedProductIds
设置为字符串数组的地方缺少一些代码。在您的代码中,您已严格将其定义为1个数组,而不是另一个。也许上述更改可以解决此问题。请确认。
问题
当具有不同类型的数组的并集时,不能在它们上调用方法。
原因
您有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[])
);
问题
当具有不同类型的数组的并集时,不能在它们上调用方法。
原因
您有String()
,因此String()
是:
Number()
当TS合并这些签名时,它将把两个Number()
签名结合在一起:
// Types
export interface IProductPrice {
id: number
}
// State
const [productPrices, setProductPrices] = useState<IProductPrice[]>([])
const [selectedProductIds, setSelectedProductIds] = useState<(string|number)[]>([])
// Delete Selected Products
const deleteSelectedProducts = () => {
setProductPrices(productPrices.filter(p => !selectedProductIds.filter(id => Number(id) === p.id).length))
setSelectedProductIds([])
}
这有点不直观,但这简化为string[] | number[]
。因为如果您有一个使用X的函数或一个使用Y的函数,那么传递的唯一安全的东西就是.filter
和 ((filterFunc: (x: string) => boolean) => string[])
| ((filterFunc: (x: number) => boolean) => number[])
或filterFunc
。
((x: number) => boolean)
| ((x: string) => boolean)
是不可能的类型,它“简化”为(x: number & string) => boolean
。因此,为什么签名是X
。
修复
理想情况下,您只会使用Y
或X & Y
,而不能同时使用。 (仅查看代码,为什么number & string
只能是数字,而“选定的产品ID”也可以是字符串,这有点神秘)
但是如果您确实需要同时支持字符串和数字,那么这里最简单的解决方法是使用never
而不是(x: never) => boolean
:单个数组类型没有尝试将两个string[]
签名合并在一起的问题。
您可以将您的状态更改为该类型:
number[]
这很简单,但是缺点是它允许混合使用字符串和数字组成的数组,这可能是不希望的。 (例如id
如果没有,您可以暂时转换为Array<string | number>
,进行过滤,然后转换回string[] | number[]
。这不是超级干净,但应该是安全的:
.filter
以上是关于'number'类型的参数不能分配给array.includes()中'never'类型的参数的主要内容,如果未能解决你的问题,请参考以下文章
参数类型“Type”不能分配给参数类型“FirebaseUser”
参数类型“PointerEvent”不能分配给参数类型“PointerDownEvent”
flutter error:参数类型'Future '无法分配给参数类型'小部件'
在 swift 中将 String 类型数组转换为 Float 类型数组 不能将类型 'String' 的值分配给类型 'Double' 的下标。