我有以下打字稿代码,该代码使用区分的并集来区分某些相似的对象:
interface Fish {
type: 'FISH',
}
interface Bird {
type: 'BIRD',
flyingSpeed: number,
}
interface Ant {
type: 'ANT',
}
type Beast = Fish | Bird | Ant
function buildBeast(animal: 'FISH' | 'BIRD' | 'ANT') {
const myBeast: Beast = animal === 'BIRD' ? {
type: animal,
flyingSpeed: 10
} : {type: animal}
}
在函数buildBeast
中,它接受一个符合我的types
类型的所有可能的Beast
的字符串,但不允许我将myBeast
声明为类型Beast
由于此错误:
Type '{ type: "BIRD"; flyingSpeed: number; } | { type: "FISH" | "ANT"; }' is not assignable to type 'Beast'.
Type '{ type: "FISH" | "ANT"; }' is not assignable to type 'Beast'.
Type '{ type: "FISH" | "ANT"; }' is not assignable to type 'Ant'.
Types of property 'type' are incompatible.
Type '"FISH" | "ANT"' is not assignable to type '"ANT"'.
Type '"FISH"' is not assignable to type '"ANT"'.
似乎所有情况下仍然都能产生正确的Beast
,但TS似乎难以强制使用不同的类型。有什么想法吗?
答案 0 :(得分:2)
TypeScript不会通过遍历联合类型并确保每种类型都起作用来control flow analysis。如果这样做了,或者您可以告诉它这样做,那会很好,并且实际上我已经made a suggestion了,但是目前不可能。
就目前而言,据我所知,解决该问题的唯一方法是我在该建议中提到的解决方法:要么进行类型断言(这是不安全的),要么使编译器经历不同的情况(这是多余的)。这是两种不同的方式:
断言:
function buildBeast(animal: 'FISH' | 'BIRD' | 'ANT') {
const myBeast: Beast = animal === 'BIRD' ? {
type: animal,
flyingSpeed: 10
} : {type: animal} as Fish | Ant;
}
通过不同情况介绍编译器:
function buildBeast(animal: 'FISH' | 'BIRD' | 'ANT') {
const myBeast: Beast = animal === 'BIRD' ? {
type: animal,
flyingSpeed: 10
} : (animal === 'FISH') ? {
type: animal
} : { type: animal };
}
嘿,如果您认为TypeScript应该允许您将控制流分析分布在并集类型上,则可以直接参考该建议并给出建议或描述您的用例。或者,如果上述解决方案对您有用,那也很好。
希望有帮助。祝你好运!