首页 > 解决方案 > 可以是 3 种集合类型的道具

问题描述

我正在尝试输入一个items基于路由参数的反应道具,它可以是 3 种集合类型之一。集合是同质的。

我的类型定义是:items: FaqFields[] | HowToVideoFields[] | GuideFields[],

我在这种道具类型上遇到错误,如下所示:

[flow] property `answer` is missing in `HowToVideoFields` [1] but exists in `FaqFields` [2]. (References: [1] [2])
[flow] property `question` is missing in `HowToVideoFields` [1] but exists in `FaqFields` [2]. (References: [1] [2])
[flow] string literal `howTo` [1] is incompatible with string literal `faq` [2] in property `contentType`. (References: [1] [2])

以下是这些字段形状中的每一个供参考

export type SupportCategories = 'SomeCat' | 'SomeOtherCat';

export type FaqFields = {
  answer: string,
  category: SupportCategories[],
  contentType: 'faq',
  id: string,
  question: string,
  slug: string,
  title: string,
};

export type GuideFields = {
  category: SupportCategories[],
  contentType: 'guide',
  id: string,
  slug: string,
  title: string,
};

export type HowToVideoFields = {
  category: SupportCategories[],
  contentType: 'howTo',
  id: string,
  slug: string,
  title: string,
  youtubeId: string,
};

这是我的使用方式items

  renderSupportItems(
    items
  ): ?(Element<typeof Accordion> | Element<typeof Masonry>) {
    if (items) {
      if (items.every(i => i.contentType === 'faq')) {
        return (
          <Accordion>
            {items.map(({category, question, answer, id}) => (
              <Accordion.Item key={id}>
                {{
                  label: (
                    <Styled.FaqTitleWrapper>
                      <Styled.FaqEyebrow>
                        <Text tag="h2" theme="newsBody">
                          {category.join(' | ')}
                        </Text>
                      </Styled.FaqEyebrow>
                      <Text tag="h2" theme="narrowBodyLarge">
                        {question}
                      </Text>
                    </Styled.FaqTitleWrapper>
                  ),
                  content: (
                    <Styled.FaqContent>
                      <Text tag="p" theme="newsBody">
                        <Markdown>{answer}</Markdown>
                      </Text>
                    </Styled.FaqContent>
                  ),
                }}
              </Accordion.Item>
            ))}
          </Accordion>
        );
      }

      if (items.every(i => i.contentType === 'guide') || items.every(i => i.contentType === 'howTo')) {
        return (
          <Masonry>{items.map(i => <SupportCard key={i.id} {...i} />)}</Masonry>
        );
      }
    }

    return null;
  }

标签: reactjsflowtype

解决方案


我最好的建议(主要来自我使用 flow 的经验)是稍微改变items使用方式,并做如下的事情:

renderSupportItems(
    items
  ): ?(Element<typeof Accordion> | Element<typeof Masonry>) {
    if (items) {
      if (items.every(i => i.contentType === 'faq')) {
        return (
          <Accordion>
            {items.map((item) => {
             if (item.contentType === 'faq') {
             const {category, question, answer, id} = item;
             return (<Accordion.Item key={id}>
                {{
                  label: (
                    <Styled.FaqTitleWrapper>
                      <Styled.FaqEyebrow>
                        <Text tag="h2" theme="newsBody">
                          {category.join(' | ')}
                        </Text>
                      </Styled.FaqEyebrow>
                      <Text tag="h2" theme="narrowBodyLarge">
                        {question}
                      </Text>
                    </Styled.FaqTitleWrapper>
                  ),
                  content: (
                    <Styled.FaqContent>
                      <Text tag="p" theme="newsBody">
                        <Markdown>{answer}</Markdown>
                      </Text>
                    </Styled.FaqContent>
                  ),
                }}
              </Accordion.Item>
            ))}
          </Accordion>
        );
        };

        return null;
      }

      if (items.every(i => i.contentType === 'guide') || items.every(i => i.contentType === 'howTo')) {
        return (
          <Masonry>{items.map(i => <SupportCard key={i.id} {...i} />)}</Masonry>
        );
      }
    }

    return null;
  }

即使从 javascript 的角度来看,也没有理由进行额外contentType的检查,.map这将使流更直接地处理它现在正在处理的类型。


推荐阅读