I'm trying to create a generic text input component for our application using react and typescript. I want it to be able to either be an input element or a textarea element based on a given prop. So it looks somewhat like this:
import {TextArea, Input} from 'ourComponentLibrary'
export const Component = forwardRef((props, ref) => {
const Element = props.type === 'textArea' ? TextArea : Input
return (
<Element ref={ref} />
)
})
This code works fine. However, when trying to incorporate types it becomes a little dicey. The ref type should be either HTMLInputElement
or HTMLTextAreaElement
based on the passed type
prop. In my head, it would look something like this:
interface Props {
...
}
export const Component = forwardRef<
HTMLInputElement | HTMLTextAreaElement,
Props
>((props, ref) => {
...
});
However I know this isn't exactly what I need. Hence, the error:
Type 'HTMLInputElement' is missing the following properties from type 'HTMLTextAreaElement': cols, rows, textLength, wrap
In summary, I want the types to align so that if the type
prop is textArea
then the ref
type should be HTMLTextAreaElement
, and if the type prop is input
then the ref type should be HTMLInputAreaElement
Any advice?
Thanks.
React forwardRef is a method that allows parent components pass down (i.e., “forward”) refs to their children. Using forwardRef in React gives the child component a reference to a DOM element created by its parent component. This then allows the child to read and modify that element anywhere it is being used.
forwardRef() which means we have to apply the HOC before React.
The forwardRef hooks allows React users to pass refs to child components. The ref can be created and referenced with useRef or createRef and then passed in a parent component. Using forwardRef instead of useRef is useful when a ref needs to be accessed in a parent component.
I know I'm really late to answer this, but this is how I solved this problem. Maybe this will help someone else someday.
type InputElement = 'input' | 'textarea'
export type InputProps<E extends InputElement> = {
multiline: E extends 'textarea' ? true : false
/* rest of props */
}
const Component = React.forwardRef(function Component<E extends InputElement>(
props: InputProps<E>,
ref: React.Ref<HTMLElementTagNameMap[E] | null>,
) {
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With