Typescript conditional extends based on parameters value

You can extend interface only with statically known types. It means that does not allow you to extend SelectTypeProps with SelectTypeExtends because SelectTypeExtends is a black box. Nobody know type of T.

In order to manage this case, you should use type instead of interface:

type SelectProps = {
  tag: 'SelectProps'
}

type RadioGroupProps = {
  tag: 'RadioGroupProps'
}

type CheckboxGroupProps = {
  tag: 'CheckboxGroupProps '
}

type SelectTypeExtend<T> =
  T extends { expand: false } ? SelectProps :
  T extends { expand: true; multiple: false } ? RadioGroupProps :
  T extends { expand: true; multiple: true; } ? CheckboxGroupProps :
  never;

type SelectTypeProps<T> = { // <------ type instead of interface
  multiple?: boolean;
  expand?: boolean;
} & SelectTypeExtend<T>

Example with react components:

import React from "react";

import {
  Select,
  SelectProps,
  Checkbox,
  CheckboxGroupProps,
  Radio,
  RadioGroupProps
} from "formik-antd";


export type SelectionComponentProps =
  | { expand?: false } & { options: SelectProps }
  | { expand: true; multiple?: false } & { options: RadioGroupProps }
  | { expand: true; multiple: true } & { options: CheckboxGroupProps };

function SelectionComponent(props: SelectionComponentProps) {
  if (props.expand) {
    if (props.multiple) {
      return <Checkbox.Group {...props.options} />;
    } else {
      return <Radio.Group {...props.options} />;
    }
  }
  return <Select {...props.options} />;
};

const select: SelectProps = 'unimplemented' as any;
const radio: RadioGroupProps = 'unimplemented' as any;
const checkbox: CheckboxGroupProps = 'unimplemented' as any;

export const TestRadio = () => {
  // Accept properties from RadioGroupProps but not from SelectProps or CheckboxGroupProps
  return [
    <SelectionComponent expand options={radio} />, // ok
    <SelectionComponent expand options={select} />, // expected error
    <SelectionComponent expand options={checkbox} />, // expected error
  ]
};

export const TestCheckbox = () => {
  // Accept properties from CheckboxProps but not from SelectProps or RadioGroupProps
  return [
    <SelectionComponent expand multiple options={checkbox} />, // ok
    <SelectionComponent expand multiple options={select} />, // expected error
    <SelectionComponent expand multiple options={radio} /> // expected error
  ]
};

export const TestSelect = () => {
  // Accept properties from SelectProps but not from RadioGroupProps or CheckboxGroupProps
  return [
    <SelectionComponent options={select} />, // ok
    <SelectionComponent options={radio} />, // expected error
    <SelectionComponent options={checkbox} />, // expected error
  ]
};

Playground

I have slightly modified SelectionComponentProps type. Please keep in mind, that if you don't provide some property to react component, TS treats it as undefined and not as false, hence you need to make some of your false properties as a partial