reactjs - Hur begränsar man en generisk typ till att vara en typ som kan vara props för en React-komponent?
Jag har precis slutat kämpa med TypeScript-kompilatorn för att skapa en komponent som tar en annan komponent som en prop - och sedan kräver alla den komponentens props som props att skicka till den. (Användningsfallet är för Gatsby <PrivateRoute>-komponenter).
Jag har faktiskt lyckats få det att fungera, men problemet är att jag inte kan lista ut varför detta fungerar.
Här är ett förenklat exempel:
Wrapper-komponenten och definierade props:
type WrapperProps<T> = { component: React.ComponentType<T> } & T;
const Wrapper = <T extends object>({
component: Component,
...rest
}: WrapperProps<T>) => {
return <Component {...(rest as T)} />;
};
och den avsedda användningen:
interface person {
name: string;
age: number;
}
const ShowPerson = ({ name, age }: person) => {
return (
<h1>
{name}, {age}
</h1>
);
};
const Display = () => {
return <Wrapper component={ShowPerson} name="T" age={12} />;
};
Den del som jag inte kan lista ut varför den fungerar är i den generiska begränsningen i wrapper-komponenten. Om jag tar bort <T extends object>, får jag ett fel "konvertering av typen 'Omit<WrapperProps<T>,"component"> till typen 'T' kan vara ett misstag eftersom ingen av typerna överlappar tillräckligt med den andra
Nu är det begripligt att generiken behöver begränsas, men finns det en bättre begränsning än att använda <T extends object>? Varför fungerar inte <T extends {}>? Vad skulle vara en acceptabel och bättre generikbegränsning som skulle fungera som props för en React-komponent? extends object känns inte som den korrekta lösningen för mig.
Redigera Detta kan också fungera genom att casta ...rest as unknown as T, men jag har fortfarande svårt att förstå det:
const Wrapper = <T,>({
component: Component,
...rest
}: WrapperProps<T>) => {
return <Component {...(rest as unknown as T)} />;
};
Typescript Playground-exempel