Dynamically resolve property type based on another property value in TypeScript
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