Problem Description
I want to define two optional properties in an interface in Typescript. One and only one of these two properties must be present in the instance object of this interface.
What I have tried
interface ISidebarCommon {
/**
* The label to be used in sidebar
*/
label: string;
/**
* Icon class in string format for the icon of the sidebar image
*/
icon: string;
}
interface IRoutableSidebarItem extends ISidebarCommon {
/**
* Role number to determine which route to redirect the user to
* This property is mutually exclusive with children
*/
role: number;
}
interface ITreeSidebarItem<SI> extends ISidebarCommon {
/**
* An array of children sidebar items.
* This property is mutually exclusive with role
*/
children: SI[];
}
interface ISidebar {
[index: number]: IRoutableSidebarItem | ITreeSidebarItem<IRoutableSidebarItem
| ITreeSidebarItem<IRoutableSidebarItem>
>;
}
Problem with current solution
While the current solution makes sure that one of the two properties, i.e, role
and children
, must be present, it does not make them mutually exclusive. That is, both role
and children
may be present in the instance object and it will still pass the current interface check.
Sample of Problem
The following is an example of an instance of the ISidebar
interface where the objects contain both role
and children
and the linter still doesn't show any errors:
const sidebarBroken: ISidebar = [
{
label: 'l1',
icon: 'c1',
role: 5,
children: [
{
label: 'l2',
icon: 'c2',
role: 6,
children: [
{
label: 'l3',
icon: 'c3',
role: 7,
},
],
},
],
},
];