请考虑以下Typescript类型...
export type Dog = {
color: string,
earsFloppy: boolean,
_type: "dog"
}
export type Fish = {
color: string,
finsFlowy: boolean,
_type: "fish"
}
export type Pet = Dog | Fish;
export type PetMap = {
dog: Dog[],
fish: Fish[]
}
考虑以下功能(也在Typescript中)...
var myPetMap = { dog: [], fish: [] };
function addToPetMap(newPet: Pet): void {
myPetMap[newPet._type].push(newPet);
}
我的项目中的设置几乎相同,但是出现以下错误:
[ts] Cannot invoke an expression whose type lacks a call signature. Type '((...items: Dog[]) => number) | ((...items: Fish[]) => number)' has no compatible call signatures. [2349]
但是执行以下操作可以解决问题...
var myPetMap = { dog: [], fish: [] };
function addToPetMap(newPet: Pet): void {
switch(newPet._type) {
case 'dog':
myPetMap[newPet._type].push(newPet);
break;
case 'fish':
myPetMap[newPet._type].push(newPet);
break;
}
}
在newPet._type
存在的范围内,好像myPetMap[newPet._type].push(newPet)
的值必须是已知的或具体的。它不能存在于不能保证newPet._type
(x)或dog
的范围内。
但是,由于fish
的 type 是Dog._type
,而"dog"
的 type 是Fish._type
, "fish"
的值可以仅为为Dog._type
,而"dog"
的值可以仅为为Fish._type
。我不明白为什么
"fish"
是错误的。
当传入的myPetMap[newPet._type].push(newPet);
是Pet
时,Dog
只能是newPet._type
并且新的宠物将被添加到"dog"
中,这是myPetMap["dog"]
个对象的数组。
当传入的Dog
是Pet
时,Fish
只能是newPet._type
并且新的宠物将被添加到"fish"
中,这是myPetMap["fish"]
个对象的数组。
由于Fish
可能是两种类型的_type
属性的类型都是固定值,所以我看不出{{1} }被添加到Pet
数组中,反之亦然。无需将Dog
的值具体化或已知即可将其添加到正确的数组中。
有什么办法解决吗?是否有Typescript编译器选项或其他编写方式?
编辑:
Fish
的类型为newPet._type
。
这是我当时的想法,但是尝试更改newPet._type
的值会产生自己的错误...
string
newPet._type
答案 0 :(得分:3)
您的方法没有错,但是您确实遇到了类型系统的限制。 Typescript无法遵循变量之间的关系,因此Typescript无法分辨您的函数与该函数之间的区别:
function addToPetMap(_type: "dog" | "fish", newPet: Pet): void {
myPetMap[_type].push(newPet);
}
在上面的示例中,可以传入'dog'
和一个Fish
的实例。虽然在您的情况下这是不会发生的,因为_type
来自newPet
,编译器无法遵循此要求,它只是将newPet._type
的类型视为"dog" | "fish"
并引发错误。
您使用开关的解决方法是这样做的非常安全的方法。类型断言也是合适的。