Say I have this type:
export interface Opts {
paths?: string | Array,
path?: string | Array
You are basically looking for an exclusive union type.
It has been already proposed but unfortunately, in the end, it was declined.
I found the proposed solutions here not to my liking, mostly because I'm not a fan of fancy and complex types.
Have you tried with function overloading?
I was in a similar situation and for me, this was the solution.
interface Option1 {
paths: string | string[];
}
interface Option2 {
path: string | string[];
}
function foo(o: Option1): void;
function foo(o: Option2): void;
function foo(o: any): any {}
foo({ path: './' });
foo({ paths: '../' });
// The folling two lines gives an error: No overload matches this call.
foo({ paths: './', path: '../' });
foo({})
With arrow function the same code as above would instead be:
interface Option1 {
paths: string | string[];
}
interface Option2 {
path: string | string[];
}
interface fooOverload {
(o: Option1): void;
(o: Option2): void;
}
const foo: fooOverload = (o: any) => {};
foo({ path: '2' });
foo({ paths: '2' });
// The following two lines gives an error: No overload matches this call.
foo({ paths: '', path: 'so' });
foo({});
Hope this helps you out!