我已经创建了一个人为的示例(打字稿游乐场)来尝试说明我的问题。foo
,bar
和baz
是互斥的。我只是在寻找一种解决方案,该解决方案将XYZ
作为我功能参数的类型。我已经知道X
类型可以在这里工作。
type X = { foo: string; bar?: undefined; baz?: undefined }
type Y = { foo?: undefined; bar: string; baz?: undefined }
type Z = { foo?: undefined; bar?: undefined; baz: string; }
type XYZ = X | Y | Z;
function foo(xyz: XYZ): string | undefined {
return xyz.foo;
}
理想情况下,我只需要定义所需的部分:
type X = { foo: string };
type Y = { bar: string };
type Z = { baz: string };
但是没有冗余,我会收到此错误消息:
Property 'foo' does not exist on type 'XYZ'.
Property 'foo' does not exist on type 'Y'.
我已经尝试过,但是我最终得到了看起来像 undefined & string
的类型:
type XYZ = { foo?: undefined; bar?: undefined; baz?: undefined } & (X | Y | Z);
我认为您正在寻找&
(交叉点类型),而不是|
(联合类型):
type X = { foo: string };
type Y = { bar: string };
type Z = { baz: string };
type XYZ = X & Y & Z;
来自交叉点类型文档:
交点类型将多种类型组合成一种。这使您可以添加现有类型以获得具有所需功能的单一类型。例如,
Person & Serializable & Loggable
是Person
和Serializable
和Loggable
。这意味着这种类型的对象将具有所有三种类型的所有成员。
在操场上工作。
也就是说,如果您要说的是,当foo
存在时,bar
和baz
必须不确定,我想您会坚持使用交叉点,但是然后您必须告诉Typescript,在使用类型的断言中使用它之前,请先知道foo
。因为否则,它不知道您正在处理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;
}
在操场上。
我认为没有类型断言的方法没有办法。(但同样,我不是Titian Cernicova-Dragomir。:-))
另一种选择是使用功能过载,但是您已经说明要保留XYZ
,并且仍然需要您具有逻辑来检测您正在处理的内容。Div>