Search code examples
reactjstypescriptreact-proptypes

Prevent props using propTypes


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?


Solution

  • 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