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



我已经创建了一个人为的示例(打字稿游乐场)来尝试说明我的问题。foobarbaz是互斥的。我只是在寻找一种解决方案,该解决方案将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 & LoggablePersonSerializableLoggable。这意味着这种类型的对象将具有所有三种类型的所有成员。

在操场上工作。


也就是说,如果您要说的是,当foo存在时,barbaz 必须不确定,我想您会坚持使用交叉点,但是然后您必须告诉Typescript,在使用类型的断言中使用它之前,请先知道foo。因为否则,它不知道您正在处理X,而不是YZ。例如:

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>

最新更新