-
-
Notifications
You must be signed in to change notification settings - Fork 231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mutually exclusive group #138
Comments
This would be really nice to have it included in It is possible to define such shape using discriminated union type, but it requires having one shared property to infer correct type. That is acceptable approach for many cases, where some properties would be shared anyway. interface TextInput {
type: "text";
value: string;
}
interface NumberInput {
type: "number";
value: number;
}
function Input(props: TextInput | NumberInput) {} But then there are cases where some properties should be mutually exclusive, without the necessity to use additional interface ImageFile {
/** Local file URL is resolved internally. */
file: File;
}
interface ImageSrc {
src: string;
}
function Image(props: ImageFile | ImageSrc) {} We want to say that Image({ file: foo, src: "bar" }); // no error The solution is to extend our interfaces to also describe properties which should not be present, defining them as optional value of interface ImageFileX {
/** Local file URL is resolved internally. */
file: File;
src?: undefined;
}
interface ImageSrcX {
src: string;
file?: undefined;
}
function ImageX(props: ImageFileX | ImageSrcX) {} Now it works as expected. ImageX({ file: foo }); // ok
ImageX({ src: "bar" }); // ok
ImageX({ file: foo, src: "bar" }); // error But there is a lot of boilerplate which does not really provide any additional information and I think it actually makes the code less readable, especially when you have multiple related properties bound together... interface BaseInput<T> {
name?: string;
value: T;
error: boolean;
onChange: (next: T) => void;
}
interface ManagedInput<T> {
name: string;
value?: never;
error?: never;
onChange?: never;
} There seems to be quite long discussion in related issue presenting some solutions, so it might be worth exploring... |
Is your feature request related to a real problem or use-case?
It'd be a good idea to be able to create mutually exclusive groups for options that cannot coexist.
Use cases:
Many APIs have filters of which exactly one can be used at a time. So to define their schemas, such a feature can prove to be really helpful.
Also, there are many options/flags which cannot be used simultaneously in one command line.
Describe a solution including usage in code example
Possible code example:
Say, we have 2 properties declared in a mutually exclusive group in an interface. Now, exactly one of those properties can exist, with no two properties coexisting simultaneously in an object having type of that interface.
Additionally, we can also think of making the entire group optional, maybe with something like this:
Example:
Now, if this interface is used as a function parameter:
The following code snippet should throw an error, since the two properties arg1 and arg2 cannot coexist in the same object.
Who does this impact? Who is this for?
Many people using TypeScript must have felt the need for declaring mutually exclusive groups.
The text was updated successfully, but these errors were encountered: