简体   繁体   English

如何为我的联合类型创建一个 Typescript 类型守卫

[英]How to create a Typescript type guard for my union type

I have the following Typescript types:我有以下 Typescript 类型:

export type TeaserOne = { __typename: 'TeaserOne' } & TeaserOneItem;
export type TeaserTwo = { __typename: 'TeaserTwo' } & TeaserTwoItem;
export type TeaserThree = { __typename: 'TeaserThree' } & TeaserThreeItem;

export type Teaser = TeaserOne | TeaserTwo | TeaserThree;

export type FilteredTeasers = Exclude<Teaser, TeaserThree >;

export type TeaserItem = TeaserOneItem | TeaserTwoItem | TeaserThreeItem;

For example the item types looks a bit like:
// TeaserOneItem:

export interface TeaserOneItem {
  type: string;
  id: string;
  title: string;
  lead?: string;
}

// TeaserTwoItem:

export interface TeaserTwoItem {
  type: string;
  id: string;
  title: string;
  duration?: string;
  image?: Image;
}

In a certain React component I need to create a Typescript type guard :在某个 React 组件中,我需要创建一个Typescript 类型保护

const filteredItems = data.items?.filter(
    (item) =>
      item?.__typename.includes('TeaserOne') || item?.__typename.includes('TeaserTwo')
  );
// -->  Maybe also I can refactor above with a type guard, but how exactly?

{filteredItems.map((node, index) => {
          if (isTeaserOne() // <-- Here I want to use a type guard) {
            const teaserOne = node as TeaserOneType;

            return (
              <TeaserOne
                key={teaserOne.id}
                title={teaserOne.title}
                lead={teaserOne.lead}
              />
            );
          }
          const teaserTwo = node as TeaserTwoType;
          return (
            <TeaserTwo
              key={teaserTwo.id}
              title={teaserTwo.title}
              image={teaserTwo.image}
            />
          );
        })}

How do I create a nice and clean type guard function isTeaserOne() ?如何创建一个漂亮干净的类型保护 function isTeaserOne() So far I have:到目前为止我有:

const isTeaserOne = (teaser: TeaserItem): teaser is TeaserOneItem =>
    typeof teaser === 'object' && teaser.type.includes('TeaserOne');

But how do I have to use this?但是我该如何使用它呢? Or do I have to refactor above type guard function?或者我是否必须重构上面的类型保护 function?

In your code isTeaserOne = (teaser: Teaser) use Teaser class, so have the __typename property, you can use it directly在你的代码isTeaserOne = (teaser: Teaser)使用 Teaser class,所以有 __typename 属性,你可以直接使用它

    const isTeaserOne = (teaser: Teaser): teaser is TeaserOne => teaser.__typename === 'TeaserOne';
    const isTeaserTwo = (teaser: Teaser): teaser is TeaserTwo => teaser.__typename === 'TeaserTwo';
    const isTeaserThree = (teaser: Teaser): teaser is TeaserThree => teaser.__typename === 'TeaserThree';
      
   

    filteredItems.map((node) => {
           // here typeof node is Teaser 
           if (isTeaserOne(node)) { 
                // here typeof node is TeaserOne
                <TeaserOne />
            }
            if (isTeaserTwo(node)) {
                // here typeof node is TeaserTwo
                <TeaserTwo />
                }
            if (isTeaserThree(node)) { 
               // here typeof node is TeaserThree
                <TeaserThree />
                }
            return "nothing";
        })

In fact, is suppose your code is incomplete, beacause in facts you do not need a typeguard here.事实上,假设您的代码不完整,因为实际上您在这里不需要类型保护。 a simple一个简单的

if (node.__typename === "TeaserOne") { 
        // here typeof node is TeaserOne
        <TeaserOne />
    }

Would give the same results.会给出相同的结果。

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

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