Reputation: 958
so let me dive into an example:
type NodeOrMethod<T> =
| {
node?: Array<Filter<T>>;
method: Condition<T>;
}
| {
node: Array<Filter<T>>;
method?: Condition<T>;
};
interface BaseFilter {
label: string;
value?: string;
}
export type Filter<T> = BaseFilter & NodeOrMethod<T>;
Basically what I want to do is make it so the dev has to either include node
or method
- which this currently works; however, I want to take it a step further and say IF one of these is present the other CANNOT be. So if they try to include both node
and method
in the same object it would complain. Has anyone done something like this before?
Upvotes: 0
Views: 563
Reputation: 15313
I would probably use tagged unions (see the relevant section of the docs) for what you are trying to do, something like
type Node<T> = {
type: 'node',
node: Array<Filter<T>>;
}
type Method<T> = {
type: 'method',
method: Condition<T>;
}
type NodeOrMethod<T> = Node<T> | Method<T>;
cost a: NodeOrMethod<T> = { // valid
type: 'node',
node: [...]
}
cost b: NodeOrMethod<T> = { // valid
type: 'method',
method: ...
}
cost c: NodeOrMethod<T> = { // type error
type: 'method',
node: [...],
method: ...
}
Upvotes: 2
Reputation: 1224
Node/JS philosophy doesn't really work this way. Objects are given permission to have whatever they want on them and consuming code only pays attention to what it cares about. Some ways to handle this include:
All the same, the type is suspiciously overloaded with two meanings. I expect there is another pattern available that avoids this. If you're stuck in a corner with code that is not yours, then one of the above approaches should work fine.
Upvotes: 0