-
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
setter inferred from union has incorrect variance #56894
Comments
The issue title should mention setters here :p I prepared a fix for this one: #56895 I also have found that variance is actually computed incorrectly (or rather... it's not observable at all): // this really should be `in` but you can make it whatever you want here, TS won't complain
type MyType<out T> = {
set k(a: T);
get k(): unknown;
}; The problem is that |
They actually do, in certain cases. See e.g. #30769. |
Please help me. I don't understand why |
I am re-opening this issue because because it seems to have been incorrectly closed without any resolution attributed. |
Great reference. However, I am puzzled by this test case: function f3<T extends { [key: string]: any }>(obj: T) {
let foo = obj['foo'];
let bar = obj['bar'];
obj['foo'] = 123; // Error
obj['bar'] = 'x'; // Error
} I can't see the reasoning for the errors. This is runtime-error-free node JS:
|
It likely prevents invalid writes in situations like this: declare const obj: {
foo: boolean;
bar: boolean;
};
f3(obj); |
Another function format exists to get that same error behavior: function f5<T extends Readonly<{ [key: string]: any }>>(obj: T) {
let foo = obj['foo'];
let bar = obj['bar'];
obj['foo'] = 123; // Error
obj['bar'] = 'x'; // Error
}
f5(obj); What function should the user call when they don't want those errors? |
Closing as this is superseded by #56922 |
π Search Terms
setter union variance
is:issue in-title: setter (nothing relevant found)
is:issue in-title: setter union variance (nothing relevant found)
π Version & Regression Information
confirmed 4.3.5 ~ 5.3.2
β― Playground Link
playground
π» Code
π Actual behavior
The setter function has range
1|2|3
.π Expected behavior
2
, because that is the valid range that can be assigned to both setter functions in the union.2
and2
computed for function parametersa
inf2
andf3
.x
should show getters and setters instead of plain (readonly for getter) properties.Additional information about the issue
The parameter range of the union of two functions is the intersection of those two functions parameter ranges. That is because anything outside of that intersection would be invalid input in at least one of the two.
Theoretically, writes and reads of plain properties of unions of object could also "legally" have opposite variances, with writes being narrower - but they are not treated that way, which although unsound is ok because type widening is allowed for convenience.
For the special cases where user want a setter, or setter-getter same-name pair, to behave write-unsoundly exactly like a plain property, they can specify the type as being a plain type, e.g.
{ d: T }
instead of{ set d(value:T): }
. That's an argument for allowing write-sound behavior by default in a type definition{ set d(value:T): }
.The setters are converted to plain properties (and the getters are converted to a readonly plain properties (probably at point of declaration) as can be seen by tool tipping to x which shows
(parameter) x: { d: 1 | 2; readonly r: 1 | 2; } | { d: 2 | 3; readonly r: 2 | 3; }
. Related to Flow is improperly narrowing getter valuesΒ #56899.The text was updated successfully, but these errors were encountered: