我创建了一个人为的示例(Typescript Playground)来说明我的问题。 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);
答案 0 :(得分:2)
我认为您正在寻找的是&
(一个intersection type),而不是|
(一个union type):
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
必须未定义,我认为您应该坚持交集类型,但随后必须通过执行type assertion来告诉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。:-))
另一种选择是使用function overloads,但是您已经明确地说要保留XYZ
,并且仍然需要您有逻辑来检测要处理的内容以及类型断言