This answer has helped me a lot so far, but my question is a little different. I want a type that defines several available properties, but whenever an object is created with any one of those properties, then it may not have any others. The question referenced, and all of its answers, only address the case when there are only 2 properties that are exclusionary.
Minimal reproducible example:
export interface OperatorExpression {
equals?: any;
lessThan?: any;
lessThanOrEqualTo?: any;
greaterThan?: any;
greaterThanOrEqualTo?: any;
contains?: any;
// etc.
}
I want the object using this interface to only allow one of those properties on it:
const op1 = { equals: {}, greaterThanOrEqualTo: {} }; // invalid, it should only allow one property
const op2 = { lessThanOrEqualTo: {} }; // valid
Okay, this is a little contrived, but I do have a similar use case.
Following the linked answer above, and others as well, I started something like this:
export interface EqualsOperatorExpression {
equals: any;
lessThan?: never;
lessThanOrEqualTo?: never;
greaterThan?: never;
greaterThanOrEqualTo?: never;
contains?: never;
}
export interface LessThanOperatorExpression {
equals?: never;
lessThan: any;
lessThanOrEqualTo?: never;
greaterThan?: never;
greaterThanOrEqualTo?: never;
contains?: never;
}
export interface LessThanOrEqualToOperatorExpression {
equals?: never;
lessThan?: never;
lessThanOrEqualTo: any;
greaterThan?: never;
greaterThanOrEqualTo?: never;
contains?: never;
}
export interface GreaterThanOperatorExpression {
equals?: never;
lessThan?: never;
lessThanOrEqualTo?: never;
greaterThan: any;
greaterThanOrEqualTo?: never;
contains?: never;
}
export interface GreaterThanOrEqualToOperatorExpression {
equals?: never;
lessThan?: never;
lessThanOrEqualTo?: never;
greaterThan?: never;
greaterThanOrEqualTo: any;
contains?: never;
}
export interface ContainsOperatorExpression {
equals?: never;
lessThan?: never;
lessThanOrEqualTo?: never;
greaterThan?: never;
greaterThanOrEqualTo?: never;
contains: any;
}
export type OperatorExpression =
| EqualsOperatorExpression
| LessThanOperatorExpression
| LessThanOrEqualToOperatorExpression
| GreaterThanOperatorExpression
| GreaterThanOrEqualToOperatorExpression
| ContainsOperatorExpression;
Now this works, but in my opinion is very clunky. If I need to add a new operator, then I have to go back through each other operator's interface, and define the one I'm adding as never
.
Is there any cleaner way to do this in Typescript, or am I stuck with the mountain of boilerplate I have to update on each new addition?