I have the following TypeScript interface:
interface SelectProps { options: Option[]; value: string[]; onChange: (value: string[]) => void; }
I want to add boolean called isMultiple
that will change the types of the other properties.
When isMultiple=true
value:string[]
onChange: (value: string[]) => void;
When isMultiple=false
value:string
onChange: (value: string) => void;
Is it possible to dynamically set the type of other properties based on the value of one property?
It's a bit late but I hope it helps others like it helped me.
Discriminated unions, also known as tagged unions or algebraic data types can be used to solve this problem.
interface MultipleSelectProps { isMultiple: true; options: string[]; value: string[]; onChange: (value: string[]) => void; } interface SingleSelectProps { isMultiple: false; options: string[]; value: string; onChange: (value: string) => void; } type SelectProps = MultipleSelectProps | SingleSelectProps;
Usage example:
function Select(props: SelectProps) { if (props.isMultiple) { const { value, onChange } = props; onChange(value); } else if (props.isMultiple === false) { const { value, onChange } = props; onChange(value); } }
Note: When
isMultiple
isundefined
ornull
it is not possible to infer the specific type ofSelectProps
. In these cases is necessary to do a strict comparisonisMultiple === false
.
Source: https://blog.mariusschulz.com/2016/11/03/typescript-2-0-tagged-union-types
You can make use of typescript Distributive Conditional Types https://www.typescriptlang.org/docs/handbook/2/conditional-types.html
So your type will look like this:
type SelectProps<TMultiple = boolean> = TMultiple extends true ? { isMultiple: TMultiple; options: string[]; value: string[]; onChange: (value: string[]) => void; } : { isMultiple: TMultiple; options: string[]; value: string; onChange: (value: string) => void; };
Here is a quick example: https://stackblitz.com/edit/typescript-9jgvys
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