-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Discriminated union parameter destructuring doesn't work if the fields have defaults #50139
Comments
FYI, your example does not include any conditional types. It includes union types. |
Your code actually works without the default values. See #44730. |
I called it "condition" here as children can only be of type string, when isText is also true. It is a condition of sorts, but not a Conditional Type of TypeScript of course. |
The proper term for what you are referring to is discriminated union. If you call it a conditional type you'll just confuse everyone because that refers to an entirely different concept. |
Maybe this is a request to support discriminated union destructuring with defaults, but the issue text would need reworking to adequately convey that |
IMO this is just a bug. The presence of the defaults shouldn't matter. |
Default values may produce unexpected behaviors. Consider this code: function Eingabefeld({
isText = false,
children = 0,
}:(
// The default is { isText: false, children: 0 },
// which is a valid branch of the discriminanted union, right?
{
isText: true,
children?: string
} | {
isText: false,
children?: number
}
)) {
console.log(isText, children);
if (isText === true) {
let data:string = children
}else if (isText === false) {
let data:number = children
}
}
Eingabefeld({isText: true})
// oops, we got {isText: true, children: 0} |
TypeScript shall in this case notify the user about the occurring invalid state. This would be another way of supplying default values, without encountering this scenario.
|
Yes, the default parameters work well, and in this case the type of |
I've encountered the same issue, while trying to write some React prop types that includes a discriminated union. Are there any news on this might be fixed? The code, I have: type WithIsMultiFieldProps<
Value,
Props,
> =
| ({
isMulti?: false | undefined;
value?: Value;
} & Props)
| ({
isMulti: true;
value?: Value[];
} & Props);
type SelectProps<I extends Record<string, any>> =
WithIsMultiFieldProps<I, {
label?: string;
items: I[];
}>
const Select = <I extends Record<string, any>>(
{
isMulti, // If I add '= false' here, it will break
value,
}: SelectProps<I>,
) => {
if (isMulti) {
value
// ^? (parameter) value: I[] | undefined
} else {
value
// ^? (parameter) value: I | undefined
}
} |
I really hope that this issue will also take into account the default props values that are not passed, that is, |
cross-linking #46266 (comment) |
Suggestion
Cleverly preserve the conditional type of variables of an de-structured object, which may be of 2 or more object types.
🔍 Search Terms
in:title destructuring assignment condition*
in:title destructuring assignment object
in:title destructuring assignment or
✅ Viability Checklist
My suggestion meets these guidelines:
💻 Use Cases
A component or function can work with two or more types. As an example let us say numbers and strings.
For the type string the component may accept additional properties, which are not applicable to numbers and vise versa.
This can be enforced by a type rule by creating multiple object types and allowing the input to only be one or the other
Now, it would be great if it would still be possible to use an destructuring assignment on the input object, wouldn't it?
📃 Motivating Example
The input to the function is an object. The general layout of the object stays the same, but the type rules should enforce a more specific rule, which allows properties to be of a certain type only if other properties are also of a certain specific type.
TypeScript cannot tell that if (isText===true) children can only be of type string. Instead TypeScript assumes that children can be both of type number and string unaffected by the if condition.
Note: This is a oversimplified example to keep the code snipped short and clean. IRL you could use it in more complex cases, where it makes proper sense to use such a feature.
What do you want to use this for?
Being able to also destructure objects which may be of different types.
What workarounds are you using in the meantime?
Instead of destructuring the object and access the properties individually, I have to use the object and access its properties.
Or use two destructuring assignment after the "if"-statement.
What shortcomings exist with current approaches?
Simply more code needs to be written. When wanting to use destructuring assignments, two or more identical destructuring assignments need to be written and the alternative is to access the property from the object, requiring repeating the objects name a bunch of times, making the code more bloated in either way.
The text was updated successfully, but these errors were encountered: