Home > OS >  typescript interface, if one, other required
typescript interface, if one, other required

Time:09-29

It's possible to create an interface with multiples properties, and if one of these is use, an other is also required ?

For example :

interface MyProps {
  onPressAll: () => void;
  icon?: ImageSourcePropType;
  onPressIcon?: () => void;
}

What I want is: if icon is set, then onPressIcon is required (or vice versa), else no one should be used.

for example, when I call my component:

<MyComponent
   onPressAll={() => {}}
   icon={myIcon}
/>
// This should return an error because onPressIcon is missing

<MyComponent
   onPressAll={() => {}}
   onPressIcon={() => {}}
/>
// This should return an error because icon is missing



<MyComponent
   onPressAll={() => {}}
/>
// Good

<MyComponent
   onPressAll={() => {}}
   onPressIcon={() => {}}
   icon={myIcon}
/>
// Good

Thanks !

CodePudding user response:

Use Discriminating Unions.

interface PropsWithIcons {
  onPressAll: () => void;
  hasIcon: true
  icon: ImageSourcePropType;
  onPressIcon: () => void;
}

interface PropsWithoutIcons {
  hasIcon: false
  onPressAll: () => void;
}

type MyProps = PropsWithIcons | PropsWithoutIcons

var obj: MyProps = {} as MyProps

if (obj.hasIcon) {
  console.log(obj.icon, obj.onPressIcon)
}
else {
  console.log(obj.icon, obj.onPressIcon) // errors
}

playground

CodePudding user response:

You can't do that with an interface. You need to use a union:

type MyPropsCommon = {
  onPressAll: () => void;
} 
type MyProps = MyPropsCommon & (
    | { icon?: undefined, onPressIcon?: undefined}
    | {
        icon: ImageSourcePropType;
        onPressIcon: () => void;
    })

Playground Link

CodePudding user response:

You could just extend interfaces:

interface MyCommonProps
{
    onPressAll: () => void;
}

interface MyIconProps extends MyCommonProps
{
    icon: ImageSourcePropType;
    onPressIcon: () => void;
}

You can also combine types so that all properties are required:

interface MyOtherProps 
{
    other: number;
}

type MyProps = MyIconProps & MyOtherProps;

Choose what fits your purpose.

  • Related