-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Returned Enum value has its type needlessly widened #20254
Comments
This is working as intended. See #10676 (comment). |
Interesting, thanks for the linking to that explanation!
Here is an example where the return type is not a singleton literal type but a union of objects containing literal types, and the compiler still appears to widen both literal types to their enum union type: {
enum Item {
potato = 'potato',
cucumber = 'cucumber',
}
{
const get = () => true ? { item: Item.potato, otherVar: true } : { item: Item.cucumber };
/* Unexpected error:
Type '{ item: Item; otherVar: boolean; } | { item: Item; }' is not assignable to type '{ item: Item.potato; otherVar: boolean; } | { item: Item.cucumber; }'.
Type '{ item: Item; otherVar: boolean; }' is not assignable to type '{ item: Item.potato; otherVar: boolean; } | { item: Item.cucumber; }'.
Type '{ item: Item; otherVar: boolean; }' is not assignable to type '{ item: Item.cucumber; }'.
Types of property 'item' are incompatible.
Type 'Item' is not assignable to type 'Item.cucumber'.
*/
const result: { item: Item.potato; otherVar: boolean } | { item: Item.cucumber } = get();
result;
}
} Is this also expected behaviour, or a separate issue? |
@OliverJAsh My comment above was regarding literal types as the actual return type. In your example the return type is a union of object types, and the literal types are widened because they are inferred for a mutable location (i.e. a property in an object literal). That is the expected behavior. |
Aha, good to know, thanks. Here's an example for anyone else who might be interested: {
enum Item {
potato = 'potato',
cucumber = 'cucumber',
}
{
const x = { item: Item.potato }
/* Error:
Type '{ item: Item; }' is not assignable to type '{ item: Item.potato; }'.
Types of property 'item' are incompatible.
Type 'Item' is not assignable to type 'Item.potato'. */
const result: { item: Item.potato; } = x;
result;
}
// workaround 1: type assertion on property
{
const x = { item: Item.potato as Item.potato }
const result: { item: Item.potato; } = x;
result;
}
// workaround 2: avoid inference
{
const x: { item: Item.potato; } = { item: Item.potato }
const result: { item: Item.potato; } = x;
result;
}
} |
Also for anyone else who is interested, here is some discussion about widening in object literals and a proposal to change this #20195 |
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed. |
TypeScript Version: 2.7.0-dev.20171124
Code
Expected behavior:
Type of
getPotato1
should be inferred as() => Item.potato
.Actual behavior:
Type of
getPotato1
is "needlessly" widened to() => Item
.cc @OliverJAsh
The text was updated successfully, but these errors were encountered: