简体   繁体   English

Typescript 对象的 Arrays 联合

[英]Typescript Union on Arrays of Objects

Fiddling around with a union of arrays which contains objects.摆弄包含对象的联合 arrays。 Expected that TS is able to guard the correct type but I guess I am missing smth here:预计 TS 能够保护正确的类型,但我想我在这里遗漏了 smth:

type A = ReadonlyArray<
  | { readonly __typename: 'EmbedParagraph' }
  | { readonly __typename: 'EntityQueueParagraph' }
  | null
> | null;

type B = ReadonlyArray<
  | { readonly __typename: 'EmbedParagraph' }
  | {
      readonly __typename: 'EntityQueueParagraph';
      readonly id: string | null;
      readonly title: string | null;
    }
  | null
> | null;

function test(paragraphs: A | B) {
  paragraphs?.forEach((paragraph) => {
    /**
     * TS OUTPUT:
     * (parameter) paragraph: {
     *     readonly __typename: "EmbedParagraph";
     * } | {
     *     readonly __typename: "EntityQueueParagraph";
     * } | {
     *     readonly __typename: "EmbedParagraph";
     * } | {
     *     readonly __typename: "EntityQueueParagraph";
     *     readonly id: string | null;
     *     readonly title: string | null;
     * } | null
     */
    if (paragraph?.__typename === 'EntityQueueParagraph') {
      console.log(paragraph);
      /**
       * TS OUTPUT:
       * (parameter) paragraph: {
       *     readonly __typename: "EntityQueueParagraph";
       * }
       */
    }

    if (paragraph && 'id' in paragraph) {
      console.log(paragraph);
      /**
       * TS OUTPUT:
       * (parameter) paragraph: never
       */
    }
  });
}

My thought was, that after the .__typename check, there are both options available.我的想法是,在.__typename检查之后,两个选项都可用。 But I am only able to use the entity queue defined in type A .但我只能使用类型A中定义的实体队列。 Order does not seem to be the reason.命令似乎不是原因。

Same goes for the 2nd condition where I would expect that TS infers type B because the id field is only available there.第二个条件也是如此,我希望 TS 推断类型B因为id字段仅在那里可用。

Hope you can give me a hint or a further read.希望你能给我一个提示或进一步阅读。 Thanks a lot!非常感谢! bw体重

EDIT编辑
After adding a new key to type A s EntityQueueParagraph typing (added foo: number ), TS is able to distinguish the two types... unfortunately not usable for my situation.添加新键以键入A s EntityQueueParagraph键入(添加foo: number )后,TS 能够区分这两种类型……不幸的是,我的情况不可用。

Apparently with a map , instead of forEach you already have better inheritance. And changing from paragraphs?.显然使用map而不是forEach你已经有了更好的 inheritance。从paragraphs?. to paragraphs && paragraphs.paragraphs && paragraphs. when checking the __typename fixed your issue.检查__typename时解决了您的问题。

type A = ReadonlyArray<
  | { readonly __typename: 'EmbedParagraph' }
  | { readonly __typename: 'EntityQueueParagraph' }
  | null
> | null;

type B = ReadonlyArray<
  | { readonly __typename: 'EmbedParagraph' }
  | {
      readonly __typename: 'EntityQueueParagraph';
      readonly id: string | null;
      readonly title: string | null;
    }
  | null
> | null;

function test(paragraphs: A | B) {
  paragraphs?.map((paragraph) => {
    if (paragraph && paragraph.__typename === 'EntityQueueParagraph') {
      console.log(paragraph);
    }

    if (paragraph && 'id' in paragraph) {
      console.log(paragraph);
    }
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM