javascript - 具有强类型属性的自定义类型中的类型假设
问题描述
考虑以下 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
不保证值为dog
(x)or的范围内fish
。
但是,因为is 的类型和Dog._type
is"dog"
的类型,所以的值只能Fish._type
是,的值只能是。我不明白为什么"fish"
Dog._type
"dog"
Fish._type
"fish"
myPetMap[newPet._type].push(newPet);
是错误的。
当Pet
传入的是 aDog
时,newPet._type
只能是"dog"
并且新宠物将被添加到myPetMap["dog"]
,这是一个Dog
对象数组。
当Pet
传入的是 aFish
时,newPet._type
只能是"fish"
并且新宠物将被添加到myPetMap["fish"]
,这是一个Fish
对象数组。
因为这_type
两种类型的属性类型Pet
可能是一个固定值,所以我看不出在将 aDog
添加到Fish
数组时会出现任何类型不匹配问题,反之亦然。newPet._type
为了将其添加到正确的数组中,不需要将其值具体化或已知。
有没有办法解决?任何 Typescript 编译器选项或不同的编写方式?
编辑:
的类型
newPet._type
是string
。
这是我在某一时刻的想法,但是试图改变 的值会newPet._type
产生它自己的错误......
newPet._type = "Something Else";
[ts] Type '"Something Else"' is not assignable to type '"dog" | "fish"'. [2322]
(property) _type: "dog" | "fish"
解决方案
您的方法没有任何问题,但是您确实遇到了类型系统的限制。打字稿不能遵循变量之间的关系,所以打字稿不能告诉你的函数和这个函数之间的区别:
function addToPetMap(_type: "dog" | "fish", newPet: Pet): void {
myPetMap[_type].push(newPet);
}
在上面的示例中,可以传入'dog'
一个Fish
. 虽然在你的情况下这是不可能发生的,因为_type
来自newPet
编译器不能遵循这个,它只是看到newPet._type
as的类型"dog" | "fish"
并引发错误。
您使用开关的解决方法是非常安全的方法。类型断言也是合适的。
推荐阅读
- python - 将列值转换为 pandas 数据框中的 column_name
- iis - 如何让 Windows 7 中的 IIS (6.1) 访问 LocalMachine (storeLocation) 和 My (storeName) 中的证书?
- android - PWA Add to Home 在 Android 设备中做了不同的行为
- c# - 为什么 NUnit 框架会抛出 DateTime AssertionException?
- java - Consul on Docker Swarm 与 Spring Boot 客户端
- python - 如何从windows上开发的python脚本在mac上创建可执行文件
- configuration - 如何在 EMR 集群 boostrap 上设置 livy.server.session.timeout?
- react-native - 反应导航破坏屏幕
- google-chrome - 为什么 Chrome 无法识别我的渐进式网络应用?
- django - ModuleNotFoundError:即使在重新检查我已安装软件包后,也没有名为“通道”的模块