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

时间:2019-03-14 17:29:39

标签: typescript

我创建了一个人为的示例(Typescript Playground)来说明我的问题。 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);

1 个答案:

答案 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 & LoggablePerson以及SerializableLoggable。这意味着此类型的对象将具有所有三种类型的所有成员。

Working on the playground


也就是说,如果您说foo存在时,barbaz 必须未定义,我认为您应该坚持交集类型,但随后必须通过执行type assertion来告诉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;
}

On the playground

我认为没有类型断言没有办法做到这一点。 (但同样,我不是Titian Cernicova-Dragomir。:-))


另一种选择是使用function overloads,但是您已经明确地说要保留XYZ,并且仍然需要您有逻辑来检测要处理的内容以及类型断言