React组件通常接受一些道具并将它们传递给孩子。如果子项上的一个或多个道具由于子项defaultProps
的指定是可选的,那么如何为接受两个子项的父项定义type
或interface
和孩子的道具正确吗?
考虑以下说明性示例:
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>;
然后我们发现title
和body
现在是可选的,这不是我们想要的。
在剩下DRY的同时,我应如何为Section
指定道具来规定title
和body
是必需的,而imgSrc
是可选的?
答案 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.defaultProps
和Partial
如何形成此构造的更多详细信息,请参见Advanced Types documentation。