typescript

Dynamically resolve property type based on another property value in TypeScript


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

When isMultiple=false

Is it possible to dynamically set the type of other properties based on the value of one property?


Solution

  • 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 is undefined or null it is not possible to infer the specific type of SelectProps. In these cases is necessary to do a strict comparison isMultiple === false.

    Source: https://blog.mariusschulz.com/2016/11/03/typescript-2-0-tagged-union-types