Repository navigation
Description
Bug Report
🔎 Search Terms
variance, methods, generics
NB: I did not search very exhaustively, but I did minimize the examples, so should be pretty easy to review and close as dupe or "by design" or whatever.
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about
strictFunctionTypes
⏯ Playground Link
Variance checking does not interact correctly with extends:
Variance checking does not interact correctly with "records with methods" types:
💻 Code
Variance checking does not interact correctly with extends:
type F<out A, out B> = <X extends A = A>(v: X) => B
const a: F<never, never> = v => v
const b: F<unknown, never> = a
const result: never = b(42) // whoopsVariance checking does not interact correctly with "records with methods" types:
type X<out S> = {
x(s: S): never
}
const a: X<never> = { x: s => s }
const b: X<unknown> = a
const whoops: never = b.x(42)🙁 Actual behavior
In both cases the typechecker allows me to inhabit never.
🙂 Expected behavior
The typechecker should reject my incorrect variance annotations (F<out A, ...> and X<out S>) and not allow me to inhabit never.
Incidentally this came to light out of some discussion in the "forall for non-functions" issue here: #17574 (comment), but these things don't really seem materially related.
Related to #48240.
Activity
scorbiclife commentedon Mar 12, 2023
Came here to report that the
outkeyword is optional and it also happens here:masaeedu commentedon Mar 12, 2023
@nightlyherb Hmm, not sure I'm following. The
outkeyword in the repros given is material, the point is to demonstrate that the typechecker agrees with the incorrect/unsound variance annotation given.The snippet you gave also contains an
outannotation, is that a typo?scorbiclife commentedon Mar 12, 2023
I just tried to say that all the examples you gave and the example I gave exhibits buggy behavior with or without variance annotations.
The buggy behavior without variance annotations might be a separate issue, but I thought it was worth a mention since it's so similar and it might be a related issue.
masaeedu commentedon Mar 12, 2023
@nightlyherb You're right that the issues are related, in fact I think they're mostly indistinguishable. The buggy behavior we're talking about is the ability to assign
const b: ... = a, which is accepted due to the (incorrectly) assumed covariance of a particular parameter. If the typechecker correctly determined that the relevant type parameters were contravariant instead, both my incorrectoutannotations and the assignment would be rejected.RyanCavanaugh commentedon Mar 14, 2023
A type parameter appearing only in a constraint is kinda sus, and generally you would want to write
X & Ain a usage position wherever you write<X extends A>(... But that doesn't even work here. I think the variance is just not being measured correctly. Examples:scorbiclife commentedon Mar 15, 2023
I have encountered a situation where this sus usage could be useful.
May I ask, is my observation correct?
i.e. is F contravariant over Xi in current typescript?