0

I have a button that can have multiple props:

interface buttonProps {
    secondary?: boolean;
    tertiary?: boolean;
    width?: number;
    children?: any;
    icon?: string;
}

If button has icon passed with no children, I want to prevent adding props: secondary, tertiary and width. Is it possible to do with TypeScript?

Alyona
  • 1,682
  • 2
  • 21
  • 44

1 Answers1

1

Yes, it is possible:

UPDATE

type OnlyIcon = {
    icon: string;
}
type IconWithChildren = {
    secondary: boolean;
    tertiary: boolean;
    width: number;
    children: any;
    icon: string;
}

// credits goes to Titian Cernicova-Dragomir
//https://stackoverflow.com/questions/65805600/struggling-with-building-a-type-in-ts#answer-65805753
type UnionKeys<T> = T extends T ? keyof T : never;
type StrictUnionHelper<T, TAll> =
    T extends any
    ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;

type StrictUnion<T> = StrictUnionHelper<T, T>

type ButtonProps = StrictUnion<IconWithChildren | OnlyIcon>;

const props: ButtonProps = {
    icon: 'd',
} // ok

const props2: ButtonProps = {
    icon: 'd',
    secondary: true
} // error

const props3: ButtonProps = {
    icon: 'd',
    secondary: true,
    tertiary:false,
} // error

const props4: ButtonProps = {
    icon: 'd',
    secondary: true,
    tertiary:false,
    width:1
} // error

const props5: ButtonProps = {
    icon: 'd',
    secondary: true,
    tertiary:false,
    width:1,
    children:{}
} // ok

Playground

Docs: Unions, Conditional types, DIstributive conditional types

  • Won't it accept all props like this? I need that if button has `icon` prop passed, any other props added should be counted as error until `children` are added as well. – Alyona Mar 23 '21 at 16:33
  • also, can you add link to info source? – Alyona Mar 23 '21 at 16:34