使用TypeScript在React中键入默认的传递道具

时间:2019-09-28 15:06:19

标签: reactjs typescript typescript3.0

React组件通常接受一些道具并将它们传递给孩子。如果子项上的一个或多个道具由于子项defaultProps的指定是可选的,那么如何为接受两个子项的父项定义typeinterface和孩子的道具正确吗?

考虑以下说明性示例:

interface ParagraphProps {
  body: string,
  imgSrc: string,
}

interface SectionProps extends ParagraphProps {
  title: string,
}

class Paragraph extends React.Component<ParagraphProps> {
  static defaultProps = {
    imgSrc: '../images/section-break.jpg',
  };

  render() {
    const { body, imgSrc } = this.props;

    return (
      <p>{body}</p>
      {!!imgSrc && <img src={imgSrc}>}
    );
  }
}

class Section extends React.Component<SectionProps> {
  render() {
    const { title, ...rest } = this.props;

    return (
      <section>
        <h1>{title}</h1>
        <Paragraph {...rest}>
      </section>
    );
  }
}

现在,声明<Section title='T' body='B'>将导致错误:

  

类型[...]中缺少属性'imgSrc'

如果相反,我们像这样定义Section的道具:

interface SectionProps {
  title: string,
}

type FullSectionProps = Partial<SectionProps & PartialProps>;

然后我们发现titlebody现在是可选的,这不是我们想要的。

在剩下DRY的同时,我应如何为Section指定道具来规定titlebody是必需的,而imgSrc是可选的?

1 个答案:

答案 0 :(得分:1)

由于ParagraphProps接口与Paragraph组件相对应,因此保持“对齐”可能很有意义。您知道imgSrc具有默认值,因此在界面中将其标记为可选是有意义的,因为使用Paragraph组件(不仅是{{ 1}}组件)必须传入Section

imgSrc

如果不是interface ParagraphProps { body: string, imgSrc?: string, } 组件的所有用户都需要传递Paragraph(除了imgSrc组件),则将其移动可能更有意义Section的{​​{1}}组件的默认值。

最后,如果您想使其更具动态性,则可以执行以下操作,尽管此示例中的操作可能比所需的复杂。

Section

这里,imgSrc类型包含// Only needed if not 3.5+ (https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html#the-omit-helper-type) type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; interface ParagraphProps { body: string; imgSrc: string; } type PropsWithDefaults = keyof typeof Paragraph.defaultProps; type TransformedProps = Partial<Pick<ParagraphProps, PropsWithDefaults>> & Omit<ParagraphProps, PropsWithDefaults>; interface SectionProps extends TransformedProps { title: string; } class Section extends React.Component<SectionProps> { render() { const { title, ...rest } = this.props; return <Paragraph {...rest} />; } } class Paragraph extends React.Component<ParagraphProps> { static defaultProps = { imgSrc: "../images/section-break.jpg" }; render() { return null; } } <Section body="foo" title="baz" /> <Section body="foo" title="baz" imgSrc="override" /> 中的所有道具,其中TransformedProps中发现的那些道具通过使用ParagraphProps成为可选的。有关Paragraph.defaultPropsPartial如何形成此构造的更多详细信息,请参见Advanced Types documentation