I have the next component in my react application:
import "./styles.css";
type InpuType = "input" | "textarea";
interface IContainer {
name: string;
placeholder: string;
as: InpuType;
}
const Container = ({
name,
placeholder,
as,
...rest
}: IContainer &
(
| React.TextareaHTMLAttributes<HTMLTextAreaElement>
| React.InputHTMLAttributes<HTMLInputElement>
)) => {
const Comp = as || "input";
return <Comp name={name} placeholder={placeholder} {...rest} />;
};
export default function App() {
return (
<div className="App">
<Container name="hi" as="textarea" placeholder="start" />
</div>
);
}
The ...rest
are all the default props that could be added for a textarea
or input
.
I have a typescript issue here <Comp name={name} ...
, hovering over the component i get this message:
Type '{ autoComplete?: string | undefined; autoFocus?: boolean | undefined; cols?: number | undefined; dirName?: string | undefined; disabled?: boolean | undefined; form?: string | undefined; ... 261 more ...; placeholder: string; } | { ...; }' is not assignable to type 'IntrinsicAttributes & ClassAttributes<HTMLInputElement> & InputHTMLAttributes<HTMLInputElement> & ClassAttributes<...> & TextareaHTMLAttributes<...>'.
and i am not sure how to get rid of that.
Question: Why the issue appear and how to solve it?
demo:https://codesandbox.io/s/react-typescript-forked-z6dk4i?file=/src/App.tsx:379-396
CodePudding user response:
Instead of throwing all the native props using rest ({...rest}
) maybe it would be better to just differentiate the props between textarea
and input
.
interface IContainer {
name: string;
placeholder: string;
textareaProps?: React.TextareaHTMLAttributes<HTMLTextAreaElement>;
inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
}
const Container = ({
name,
placeholder,
textareaProps,
inputProps,
}: IContainer) => {
if (inputProps) {
return <input {...inputProps} name={name} placeholder={placeholder} />;
}
return <textarea {...textareaProps} name={name} placeholder={placeholder} />;
};
https://codesandbox.io/s/react-typescript-forked-j9kgh2?file=/src/App.tsx:51-523
CodePudding user response:
you should create a function and create the inputs based on what you pass to it
import "./styles.css";
type InpuType = "input" | "textarea";
interface IComp {
name: string;
placeholder: string;
as: InpuType;
rest?: any;
}
const Comp = ({ as, name, placeholder, ...rest }: IComp) => {
switch (as) {
case "input":
return <input name={name} placeholder={placeholder} {...rest} />;
case "textarea":
return <textarea name={name} placeholder={placeholder} {...rest} />;
}
};
interface IContainer {
name: string;
placeholder: string;
as: InpuType;
}
const Container = ({
name,
placeholder,
as,
...rest
}: IContainer &
(
| React.TextareaHTMLAttributes<HTMLTextAreaElement>
| React.InputHTMLAttributes<HTMLInputElement>
)) => {
return <Comp as={as} name={name} placeholder={placeholder} {...rest} />;
};
export default function App() {
return (
<div className="App">
<Container name="hi" as="textarea" placeholder="start" />
</div>
);
}