Reputation: 3255
I want a component to forward dynamic props (I'm using spread operator) and this is the code I have at the moment:
type Props = {
identifier: "YouTube";
attributes: { id: string };
} | {
identifier: "Figure";
attributes: { src: string };
};
const YouTube = ({ id }) => <p>{id}</p>;
const Figure = ({ src }) => <p>{src}</p>;
const Shortcode = ({ identifier, attributes }: Props): JSX.Element => {
switch (identifier) {
case "YouTube":
return <YouTube {...attributes} />;
case "Figure":
return <Figure {...attributes} />;
}
};
TypeScript is complaining about this:
return <YouTube {...attributes} />;
// Type '{ id: string; } | { src: string; }' is not assignable to type 'IntrinsicAttributes & { id: any; }'.
// Property 'id' is missing in type '{ src: string; }' but required in type '{ id: any; }'.ts(2322)
return <Figure {...attributes} />;
// Type '{ id: string; } | { src: string; }' is not assignable to type 'IntrinsicAttributes & { src: any; }'.
// Property 'src' is missing in type '{ id: string; }' but required in type '{ src: any; }'.ts(2322)
If I explicitly pass the props, TypeScript behaves as expected:
<YouTube id="foo" /> // TS says this is ok
<YouTube wrong="props" /> // TS says this is missing the `id` prop
However, I need it to accept dynamic props. Any thoughts on how to solve this? Thanks.
Upvotes: 3
Views: 919
Reputation: 33061
This is because of destructuring. TS does not treat them as a part of one union.
In order to make TS happy, just don't use destructuring:
import React, { FC } from 'react';
type Props = {
identifier: "YouTube";
attributes: { id: string };
} | {
identifier: "Figure";
attributes: { src: string };
};
const YouTube: FC<{ id: string }> = ({ id }) => <p>{id}</p>;
const Figure: FC<{ src: string }> = ({ src }) => <p>{src}</p>;
const Shortcode = (props: Props): JSX.Element => {
switch (props.identifier) {
case "YouTube":
return <YouTube {...props.attributes} />; // ok
case "Figure":
return <Figure {...props.attributes} />; // ok
}
};
Upvotes: 2