Legeo
Legeo

Reputation: 792

Interface value depending on other optional interface value

I have this kind of interface

export interface IButton {
 label: string;
 withIcon?: boolean;
 underlined?: boolean;
 selected?: boolean;
 iconName?: string;
 isLink?: boolean;
 href?: string;
 onCLick?: () => void;
}

Is it possible to make conditionally the use of iconName based on the use of withIcon ?

To make an example:

<Button label='test' /> ---> this should not throw error

<Button withIcon /> this should throw an error that alert me that iconName is missing.

Upvotes: 1

Views: 47

Answers (2)

Ovidijus Parsiunas
Ovidijus Parsiunas

Reputation: 2742

You can achieve this by creating Union type of icon options as follows:

type IconOptions = { withIcon?: false; iconName?: string; } | { withIcon: true; iconName: string; }

What this means is that when withIcon is true, iconName will be required, otherwise it is not required.

You can then append this type as an intersection to IButton which will also need to be a type:

export type IButton = {
 label: string;
 underlined?: boolean;
 selected?: boolean;
 isLink?: boolean;
 href?: string;
 onCLick?: () => void;
} & IconOptions;

Playground link.

Upvotes: 3

Tobias S.
Tobias S.

Reputation: 23925

This seems to be similar to this quesion.

You can solve it by creating a union of both possible cases.

export type IButton = {
 label: string;
 underlined?: boolean;
 selected?: boolean;
 isLink?: boolean;
 href?: string;
 onCLick?: () => void;
} & ({
 iconName: string;
 withIcon: true
} | {
 iconName?: never;
 withIcon?: never | false
})

This will throw an error if one property is used without the other.

function main(){
  return (
    <>
      <Button label="abc"></Button> // valid
      <Button label="abc" iconName="abc" withIcon></Button> // valid
      <Button label="abc" withIcon></Button> // error: Property 'iconName' is missing in type
      <Button label="abc" iconName="abc"></Button> // error: Property 'iconName' is missing in type
      <Button label="abc" withIcon={false} iconName="abc"></Button> // error: Types of property 'iconName' are incompatible
    </>
  )
}

Playground

Upvotes: 1

Related Questions