Skip to content

Covariance, contravariance and assignability #55603

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

Closed
aswinsvijay opened this issue Sep 1, 2023 · 5 comments
Closed

Covariance, contravariance and assignability #55603

aswinsvijay opened this issue Sep 1, 2023 · 5 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@aswinsvijay
Copy link

aswinsvijay commented Sep 1, 2023

🔎 Search Terms

covariance
contravariance

🕗 Version & Regression Information

(Please suggest a better title 😅)

Recently Andrew Burgess posted a video related to covariance and contravariance, and also the in and out keywords

Noticed issue related to assignability while playing around with the code

  • This is the behavior in every version I tried

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.2.2&ssl=13&ssc=1&pln=15&pc=1#code/C4TwDgpgBAUg9gIygXigbwFBShAdgRwFcJiATAQWAC4oARAQ2AgG4spgAne3AZ3oGNgASzi4AkqRo9OQ3AHNW2XPQC2EKTPmsAvqwyhIUAAocRp0PCSpLUAGTo2YU3HMganYoqgAbCADcIbxoARigAHygAJnCoAGYdPQNoAEViYgAeGAA+FAdsPCISdSgACgArGhgAShQcvzghUi85CGBLGhLGjVN5GuQcmC8AeiGcAjSIcsqqmnrG4dGWtsROyShpHrkZ2ASMDFIIfm96Dmh+UWkoMsRUoppbjMss1gOjk7OL4CgnMyELG4m9wm6RMv3+CGee3OvC++FiQKKmUQOVQ1wQDxYGGhl3wABYEY9kbkfi4-iBLBi9NjYQBWAkQEHOVxPXJoylYz5QfAANnpjLB5KJqBJzIBRVYQA

💻 Code

type Job = {
  enqueuedAt: Date;
  transactionId: string;
  name: string;
};

type PriorityJob = Job & {
  priority: true;
  level: 1 | 2 | 3;
};

type Queue<J> = {
  enqueue: (j: J) => void;
  getJob: (id: string) => J;
  // enqueue(j: J): void;
  // getJob(id: string): J;
};

declare const jobQueue: Queue<Job>;
declare const priorityJobQueue: Queue<PriorityJob>;

const q3: Queue<Job> = jobQueue;
const q4: Queue<Job> = priorityJobQueue;

const q5: Queue<PriorityJob> = jobQueue;
const q6: Queue<PriorityJob> = priorityJobQueue;

🙁 Actual behavior

If the methods defined in the Queue type (without using in and out keywords) used the arrow function syntax, there are two of the four assignments which are errors.
But if using the normal function syntax, only one is erroring.

🙂 Expected behavior

Consistent behaviour is expected in all cases.

Additional information about the issue

No response

@aswinsvijay aswinsvijay changed the title Covariance contravariance and assignability Covariance, contravariance and assignability Sep 1, 2023
@fatcerberus
Copy link

fatcerberus commented Sep 1, 2023

Methods are intentionally bivariant, this is mentioned in the FAQ:
https://github.com/microsoft/TypeScript/wiki/FAQ#common-bugs-that-arent-bugs

Methods are always bivariant in their argument, while function properties are contravariant in their argument under strictFunctionTypes. More discussion here.

And from the linked issue:

Methods are excluded specifically to ensure generic classes and interfaces (such as Array<T>) continue to mostly relate covariantly. The impact of strictly checking methods would be a much bigger breaking change as a large number of generic types would become invariant (even so, we may continue to explore this stricter mode).

@aswinsvijay
Copy link
Author

aswinsvijay commented Sep 1, 2023

Agreed. But then, in the latter case, the missing error pops back up when the generic is specified to be in out.
Does that mean those keywords override bivariance 🤔 ?

@whzx5byb
Copy link

whzx5byb commented Sep 1, 2023

@aswinsvijay

Don't rely too much on these variance annotations, as they may produce unexpected behavior when fall back to structure checking. You can see the discussion here.

@andrewbranch
Copy link
Member

Does that mean those keywords override bivariance

Yes.

@andrewbranch andrewbranch added the Working as Intended The behavior described is the intended behavior; this is not a bug label Sep 1, 2023
@typescript-bot
Copy link
Collaborator

This issue has been marked as "Working as Intended" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Sep 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

5 participants