-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Generic interface should not be invariant when type arg only used in parameter list of function property #32674
Comments
I think this might be a duplicate / related to #32311. |
Is this the same or a separate issue: interface Fn<A, B> {
(a: A): B;
done: (fn: (b: B) => void) => Fn<A, void>;
}
declare const f: Fn<string, number>;
const g: Fn<"a", number> = f; // error!?
// Type 'Fn<string, number>' is not assignable to type 'Fn<"a", number>'.
// Type 'string' is not assignable to type '"a"'.(2322)
// ... but why is Fn<A, B> not contravariant in A? |
I think that might be separate because the issue you post is probably related to recursive types. My guess as to what is going on there is:
// When variance information isn't available we default to covariance. This happens
// in the process of computing variance information for recursive types and when
// comparing 'this' type arguments.
|
Thanks. I wonder if this warrants a brand new issue or should be added as a curiosity onto #1394 for a case where an explicit contravariance annotation would be useful. |
I think this warrants a new issue, at least for future referencing. The core problem is that The closest duplicate is probably #33872, but that was a specific regression. |
Here's a simpler repro: // Covariant because T[keyof T] has no alias symbol and we always relate structurally
type A<T> = T[keyof T];
declare let a1: A<{ a: bigint }>;
declare let a2: A<{ a: bigint | null }>;
a1 = a2; // Error
a2 = a1;
// Invariant because of variance measurement for B<T>
type B<T> = { prop: T[keyof T] };
declare let b1: B<{ a: bigint }>;
declare let b2: B<{ a: bigint | null }>;
b1 = b2; // Error
b2 = b1; // Error We consider It's a tough problem to solve. If type relations were fully evaluated structurally at all times we'd get the expected results, but we'd also have horrible performance (we've tried, it's not pretty). So, not sure there's much we can do here. |
Actually, let me clarify a bit.
So, the only safe thing to assume is that |
If we could manually annotate type params with a particular variance in the future, would that solve this problem? Or would we run into cases where it would be too expensive to check that the annotated variance is correct? |
TypeScript Version: 3.5.1
Search Terms:
generic interface, invariant, contravariant, type arg, parameter list, function property
Code
Expected behavior:
This should be allowed,
Actual behavior:
Playground Link: Playground
Related Issues:
The text was updated successfully, but these errors were encountered: