虽然这个问题已经问了一年多了,但我希望我的演示能够帮助到那些发现这个问题的人。
以下解释摘自《Programming Typescript》,稍作修改以适应此处的示例代码:
当isAorB
接受一个类型为"AorB"的参数时,并不意味着我们必须传递一个A
或B
——实际上,我们可以传递一个类型为A | B
的参数。
type A = { x: string ; y: string };
type B = { x: number; y: number };
type AorB = A | B;
const c = { x: "str", y: "str" };
function isAorB(p: AorB) {
if (typeof p.x === "number") {
const alsoCx = p.x;
const alsoCy = p.y;
return;
}
const alsoCx = p.x;
const alsoCy = p.y;
}
isAorB(c);
我承认,即使我盯着这段文字很长时间,我仍然不理解其中的逻辑。
但是,我尝试了很多类型的组合,并且认为Typescript假定以下内容也是可能的输入:
// The above c really satisfy type C here.
type C = { x: string | number ; y: string | number };
尽管不知道Typescript如何解析上述逻辑也许甚至不是一个答案。现在,上述行为对我来说并不那么奇怪。
注意:如果将c
定义为const c: C = ...
,则在调用isAorB(c)
时实际上会遇到错误。
既然您提到了“字面类型”,我假设您知道一个简单的解决方案是在联合对象的所有公共键中添加“唯一字面值”以区分它们。以下是一个简短的示例供那些不知道(因为还没有人使用这种解决方案的样本)的人参考。
使用唯一的字面标签解决模棱两可:
type A = { z: "A", x: string ; y: string };
type B = { z: "B", x: number; y: number };
type AorB = A | B;
function isAorB(p: AorB ) {
if (p.z === "A") {
const onlyAx = p.x;
const onlyAy = p.y;
return;
}
const onlyBx = p.x;
const onlyBy = p.y;
}
注意,使用以下形式的
c
现在调用
isAorB(c)
会导致错误。
const c = { x: "str", y: "str", z: "A" };
你可以这样做来确保 z
const c = { x: "str", y: "str", z: "A" as "A" };