联合类型允许错误分配所用类型的属性

Vin*_*yen 5 typescript

我在理解 TS 中的联合时遇到问题,为什么下面的分配是有效的?我认为这将只是为有效const a = {a:12}{a:123,b:23}{a:12,b:12,c:123}

type abcd =
    | {
        a: number;
      }
    | {
        a: number;
        b: number;
      }
    | {
        a: number;
        b: number;
        c: number;
      };

const a: abcd = {
    a:123,
    c:234
};
Run Code Online (Sandbox Code Playgroud)

游乐场链接

如果我更改csomethingElse

const a: abcd = {
    a:123,
    somethingElse:234 // Error on this line
};
Run Code Online (Sandbox Code Playgroud)

它给了我:

输入'{一个:数字;别的东西:数字;}' 不能分配给类型 'abcd'。对象字面量只能指定已知属性,并且类型“abcd”中不存在“somethingElse”。(2322)

Aay*_*rma 3

总长DR

联盟并不相互排斥。您可以查看此答案中的“解决方法”部分,以获取解决方法,以实现具有 Union 类型、never 类型和可选属性组合的类型的互斥。

Union型的工作方式更接近大门OR而不是XOR大门。也就是说,只要实例对象满足您的 Union 类型中的其中一种类型,它就被视为该 Union 类型的实例。

以下面为例:

type abcd =
  | {
    a: number;
  }
  | {
    x: number;
    y: number;
  }
  | {
    p: number;
    q: number;
    r: number;
  }
  | {
    x: number;
    y: number;
  };

const APY: abcd = {
  a: 123,
  p: 234,
  y: 1,
};
Run Code Online (Sandbox Code Playgroud)

由于常量APY包含足够的属性,可被视为{ a: number; }联合类型的实例,因此允许联合类型中存在的所有其他属性。

Union 类型施加的唯一限制是,不允许使用 Union 类型中不存在的属性,并且实例必须具有足够的属性来满足 Union 中存在的类型之一。

解决办法

虽然 Union 类型本身对您没有帮助,但您可以将它与 never 类型结合使用来达到您想要的结果:

type abcd =
  | {
    a: number;
    b?: never;
    c?: never;
  }
  | {
    a: number;
    b: number;
    c?: never;
  }
  | {
    a: number;
    b: number;
    c: number;
  };

/*
  Type '{ a: number; c: number; }' is not assignable to type 'abcd'.
  Property 'b' is missing in type '{ a: number; c: number; }' but required in type '{ a: number; b: number; c: number; }'.
*/
const a: abcd = {
  a: 123,
  c: 234,
};
Run Code Online (Sandbox Code Playgroud)