我正在创建一个网站,用户可以在其中进行一些练习,这些练习可以是不同的React组件。
一个练习有一个基本的外观(标题和完成日期(,我在包装类中有它。实际组件将从外部传递:
const exercises = [
<Exercise
key={1}
numberInLesson={1}
title={"Typing the alphabet"}
ExerciseComponent={TypingTheAlphabet}
exerciseComponentProps={{
...some props to pass to TypingTheAlphabet
}}
/>,
<Exercise
key={2}
numberInLesson={2}
title={"Which letter? - Vowels"}
ExerciseComponent={WhichLetter}
exerciseComponentProps={{
...some props to pass to WhichLetter
}}
现在我的问题是,如何在Exercise中键入exerciseComponentProps?例如,如果我通过TypingTheAlphabet
作为ExerciseComponent,我如何确保只有TypingTheAlphabet
的道具有效?
此外,我希望将道具onMarkAsCompleted
从Exercise传递到实际组件。
为了完整起见,这里是Exercise
的props接口,以及我想要完成的:
export interface ExerciseComponentProps {
onMarkAsCompleted: () => void;
}
export type ExerciseComponentType = ComponentType<ExerciseComponentProps>;
export interface CommonExerciseProps<C extends ExerciseComponentType> {
id: string;
numberInLesson: number;
title: string;
ExerciseComponent: C;
exerciseComponentProps: // how can I type this?
}
const Exercise: React.FC<CommonExerciseProps<any>> = (
props
) => {
const [exerciseCompletionDate, setExerciseCompletionDate] =
useState<Date | null>(null);
const {
numberInLesson,
title,
ExerciseComponent,
exerciseComponentProps,
} = props;
return (
<div
className="w3-padding-small"
style={exerciseCompletionDate ? { border: "1px solid green" } : {}}
>
<h3>
Exercise {numberInLesson}:
<br />
{title}
</h3>
{exerciseCompletionDate && (
<small>
Completed on {exerciseCompletionDate.toISOString().substring(0, 10)}
</small>
)}
<ExerciseComponent
onMarkAsCompleted={
!exerciseCompletionDate
? () => setExerciseCompletionDate(new Date())
: () => {}
}
{...exerciseComponentProps}
/>
</div>
);
};
export default Exercise;
export interface CommonExerciseProps<C extends ExerciseComponentType> {
id: string;
numberInLesson: number;
title: string;
ExerciseComponent: C;
exerciseComponentProps: React.ComponentProps<C>
}
反应。ComponentProps<组件类型>