[英]How do I make a React prop only required when used in the context of a Container component with Typescript?
I've been trying to fix this Typescript error I'm getting for some time now.我一直在尝试修复这个 Typescript 错误,我已经有一段时间了。
I've created a sandbox to illustrate the problem.我创建了一个沙箱来说明这个问题。 We have
我们有
App
component (this wraps everything)App
组件(这包含了所有内容)AddDateContainer
) - this renders it's children and renders either a timestamp string next to each child or the year depending on whether the child has a yearOnly
prop passed to itAddDateContainer
) - 这会呈现它的孩子并呈现每个孩子旁边的时间戳字符串或年份,具体取决于孩子是否有传递给它的yearOnly
道具Text
component - this is a super dumb component that simply renders the textToRender
prop passed to itText
组件 - 这是一个超级愚蠢的组件,它只是呈现传递给它的textToRender
道具The problem I am getting is that Typescript is complaining about me sending a yearOnly
prop to the Text
component because it is not included in Text
's interface.我遇到的问题是 Typescript 抱怨我向
Text
组件发送yearOnly
道具,因为它不包含在Text
的界面中。 I'd rather not include it in Text
's interface since it only going to be seen when used within the AddDateContainer
component.我宁愿不将它包含在
Text
的界面中,因为它只会在AddDateContainer
组件中使用时才能看到。
How can I tell typescript to ignore the yearOnly
prop in this case?在这种情况下,我如何告诉 typescript 忽略
yearOnly
道具?
this example is pretty arbitrary.这个例子很随意。 I have created this for illustration purposes.
我为了说明目的而创建了这个。 The real use case is a lot more valid
真正的用例更有效
Code,代码,
import React from "react";
interface TextInterface {
textToRender: string;
}
const Text = ({ textToRender }: TextInterface) => {
return <span>{textToRender}</span>;
};
const AddDateContainer = ({
children
}: {
children: React.ReactElement | React.ReactElement[];
}) => {
const renderDate = (yearOnly: boolean) => {
const date = new Date();
const dateToRender = yearOnly ? date.getFullYear() : date.getTime();
return <span>{dateToRender}</span>;
};
return (
<div>
{React.Children.map(children, (child) => {
/**
* IMPORTANT
* HERE WE ARE REMOVING THE yearOnly prop because it was only needed
* for the Container.
* How can we get Typescript to stop complaining!?
*/
const { format, ...originalProps } = child?.props;
return (
<span>
{React.cloneElement(child, originalProps)}{" "}
{renderDate(child.props.yearOnly)}
</span>
);
})}
</div>
);
};
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<AddDateContainer>
<Text yearOnly textToRender="I love this" />
</AddDateContainer>
</div>
);
}
Is there a reason you can't add the prop to the higher order component?有没有理由不能将道具添加到高阶组件? Something like this:
像这样的东西:
interface TextInterface {
textToRender: string;
}
const Text = ({ textToRender }: TextInterface) => <span>{textToRender}</span>;
interface AddDateHocProps extends PropsWithChildren<{}> {
readonly yearOnly: boolean;
}
const AddDateHoc = ({ children, yearOnly }: AddDateHocProps) => {
const date = new Date();
const dateToRender = yearOnly ? date.getFullYear() : date.getTime();
return (
<div>
{React.Children.map(children, (child) => (
<span>
{child}
<span>{dateToRender}</span>;
</span>
))}
</div>
);
};
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<AddDateHoc yearOnly>
<Text textToRender="I love this" />
</AddDateHoc>
</div>
);
}
What you want is not functionally distinct from this:您想要的在功能上与此没有区别:
import React from "react";
interface TextInterface {
textToRender: string;
}
const Text = ({ textToRender }: TextInterface) => {
return <span>{textToRender}</span>;
};
const FormattedDate = ({
yearOnly
}) => {
const date = new Date();
const dateToRender = yearOnly ? date.getFullYear() : date.getTime();
return <span>{dateToRender}</span>;
};
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Text yearOnly textToRender="I love this" />
<FormattedDate yearOnly />
</div>
);
}
Hi guys thanks for the response.大家好,感谢您的回复。 I've found something which isn't quite what I wanted but is flexible enough that I think I'm happy with it.
我发现了一些不是我想要的但足够灵活的东西,我认为我对它很满意。 I've used a generic in the Text interface.
我在 Text 界面中使用了泛型。 It feels like what I was trying to do ie make the Container component handle the types might not be possible.
感觉就像我试图做的,即让容器组件处理类型可能是不可能的。
Here is the change,这里是变化,
interface TextInterface {
textToRender: string;
}
const Text = <T extends TextInterface>(props: T) => {
const { textToRender } = props;
return <span>{textToRender}</span>;
};
The T
makes it so the yearOnly
can get through (any other props I might want to add for the benefit of the Container) will get through without me explicitly writing those props into the interface. T
使得yearOnly
可以通过(我可能想为容器的利益添加的任何其他道具)将通过,而无需我将这些道具明确写入界面。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.