Reputation: 45
Is there a way to create a React Component with Typescript where certain properties change their types based on the existence/type of a different property?
I am attempting to build a generic react select component, that can either be a multi select or a single select. It will have a renderValues
property that will be used to render the selected values. Ideally, if this component is a multi select, renderValues would have the signature:
(selected: T[]) => JSX.Element
and if it's a single select it would have the signature
(selected: T) => JSX.Element
An example of a multi select component would be:
<SingleOrMultiSelect
multiple={true}
value={['foo','bar']}
options={['foo','bar','biz','baz']}
renderValues={(opts: string[])=> opts.join(', ')}
name={'Example Multi Select'
/>
Here is a Typescript playground showing what I've started trying
It's based heavily off of the OverideableComponent
from Material UI but I can't seem to get this working.
Realistically I will just split this logic into a SingleSelect component and a multiselect component, or more likely just require renderValues
to always expect an array, but I am now curious if there is a clean way to achieve what I had originally sought to do.
Additional Playground link with the below answer implemented
Upvotes: 1
Views: 184
Reputation: 632
You can do something like this
interface SingleSelectProps {
multiple: true;
renderValues: (opts: string[]) => React.ReactNode
}
interface MultiSelectProps {
multiple: false;
renderValues: (opts: string) => React.ReactNode
}
type SingleOrMultiSelectProps = SingleSelectProps | MultiSelectProps;
Upvotes: 1