Typescript 删除具有相同形状的类型的冗余

Typescript 删除具有相同形状的类型的冗余,typescript,Typescript,我创建了一个人为的示例()来说明我的问题foo、bar和baz是相互排斥的。我只是在寻找一种将XYZ作为函数参数类型的解决方案。我已经知道X类型在这里可以工作 type X={foo:string;bar?:未定义;baz?:未定义} 类型Y={foo?:未定义;bar:string;baz?:未定义} 类型Z={foo?:未定义;bar?:未定义;baz:string;} XYZ型=X | Y | Z; 函数foo(xyz:xyz):字符串|未定义{ 返回xyz.foo; } 理想情况下,我

我创建了一个人为的示例()来说明我的问题
foo
bar
baz
是相互排斥的。我只是在寻找一种将
XYZ
作为函数参数类型的解决方案。我已经知道
X
类型在这里可以工作

type X={foo:string;bar?:未定义;baz?:未定义}
类型Y={foo?:未定义;bar:string;baz?:未定义}
类型Z={foo?:未定义;bar?:未定义;baz:string;}
XYZ型=X | Y | Z;
函数foo(xyz:xyz):字符串|未定义{
返回xyz.foo;
}
理想情况下,我只需定义所需的部分:

type X={foo:string};
类型Y={bar:string};
类型Z={baz:string};
但如果没有冗余,我会收到以下错误消息:

Property 'foo' does not exist on type 'XYZ'.
  Property 'foo' does not exist on type 'Y'.
我尝试过这个方法,但最终得到的类型看起来像
未定义&string

type XYZ = { foo?: undefined; bar?: undefined; baz?: undefined } & (X | Y | Z);

我想你在找的是
&
(a),而不是
(a):

从交叉点类型文档中:

交叉点类型将多个类型组合为一个。这允许您将现有类型添加到一起,以获得具有所需所有功能的单一类型。例如,
Person&Serializable&Loggable
是一个
Person
Serializable
Loggable
。这意味着此类型的对象将具有所有三种类型的所有成员


这就是说,如果你说当
foo
存在时,
bar
baz
必须是未定义的,我认为你应该坚持使用交叉类型,但在使用它之前,你必须通过执行。因为否则,它无法知道您处理的是
X
,而不是
Y
Z
。例如:

type X = { foo: string };
type Y = { bar: string };
type Z = { baz: string };
type XYZ = X | Y | Z;

function foo(xyz: XYZ): string | undefined {
    if ("foo" in xyz) { // Or whatever appropriate check
        return (xyz as X).foo;
    }
    return undefined;
}

我不认为没有类型断言就有办法做到这一点。(不过,我不是提香·塞尔尼科娃·德拉戈米尔。:-)



另一个选项是使用,但您已经明确表示要保留
XYZ
,它仍然需要您有逻辑来检测您正在处理的类型断言。

如果它有
foo
,您是说
bar
必须是
未定义的
?我不认为你可以用一个单一的类型,但我不是Titian Cernicova Dragomir,所以…至少,当前类型阻止你创建一个既有
foo
又有
bar
的对象。我不确定我是否能够在函数体中键入窄带。“我不确定我是否能够在函数体中键入窄带。”必须有某种方法(即使是我的回答中的属性检查),否则如何编写函数的逻辑?在本例中,它看起来像
XYZ
的形状是
{foo:string,bar:string,baz:string}
所以我没有像我想象的那样使用类型安全性。我希望保持
foo
bar
baz
相互排斥。我刚刚意识到,即使在我的示例中,
if(xyz.foo)
没有将
xyz.bar
缩小到
未定义的
@Wex-Heh,我刚刚意识到这可能是您正在寻找并正在更新的内容。:-)
type X = { foo: string };
type Y = { bar: string };
type Z = { baz: string };
type XYZ = X | Y | Z;

function foo(xyz: XYZ): string | undefined {
    if ("foo" in xyz) { // Or whatever appropriate check
        return (xyz as X).foo;
    }
    return undefined;
}