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?
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
Docs: Unions, Conditional types, DIstributive conditional types