可以是3种收集类型的道具

时间:2018-07-31 19:10:53

标签: reactjs flowtype

我正在尝试使一个反应道具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;
  }

1 个答案:

答案 0 :(得分:0)

我最好的建议(主要是根据我在使用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检查,这将使流程更直接地处理当前正在处理的类型。