代码之家  ›  专栏  ›  技术社区  ›  Wex

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

  •  1
  • Wex  · 技术社区  · 7 年前

    我创造了一个人为的例子( 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);
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   T.J. Crowder    7 年前

    我想你在找 & (一个 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 . 这意味着此类型的对象将拥有这三种类型的所有成员。

    Working on the playground


    如果你这么说的话 foo 存在, bar baz 必须 没有定义,我认为你应该坚持交叉类型,但是你必须告诉TypeScript你知道 type assertion . 因为否则,它不会知道你在处理 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;
    }
    

    On the playground .


    另一种选择是 function overloads XYZ 它仍然需要您有逻辑来检测您正在处理的内容,以及类型断言。

    推荐文章