Skip to content

Issue using union type with generic #2576

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
stephanedr opened this issue Apr 1, 2015 · 2 comments · Fixed by #2778
Closed

Issue using union type with generic #2576

stephanedr opened this issue Apr 1, 2015 · 2 comments · Fixed by #2778
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@stephanedr
Copy link

stephanedr commented Apr 1, 2015

Trying to convert function overloads to union type, I'm getting errors.
Here is a very simple code that shows the error:

class Animal { run() {} }
class Cat extends Animal {}
class Dog extends Animal {}

function run(a: Animal) {
    a.run();
}

function f<T extends Cat | Dog>(a: T) {
    a.run(); // OK.
    run(a); // Argument of type 'T' is not assignable to parameter of type 'Animal'.
}

I don't understand the difference TS makes between a.run() and run(a).

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Apr 1, 2015
@RyanCavanaugh
Copy link
Member

I believe this should work as you expect.

@mhegazy mhegazy added this to the TypeScript 1.5 milestone Apr 2, 2015
@JsonFreeman
Copy link
Contributor

It's true that the spec predicts that T is assignable to Animal in section 3.10.4. Namely the final bullet,

  • T is an object type, a type parameter, or the Number, Boolean, or String primitive type, Animal is an object type, and for each member M ("run") in Animal,
    • M ("run") is a property and T has an apparent property N "run"

and so forth.

It is possible to fix the compiler to match this behavior. However, it does not scale to union types. For example, even if the compiler matches the spec, it would not work if the run function took a Cat | Dog instead of an Animal.

I believe the fix we need here (and it needs to be fixed in the spec as well) is that if the source type is a type parameter whose base constraint is a union type, then we need to check if that union type is assignable to the target. I will try to make this change, and see what the outcome is. Then we can change it in the spec if everybody is happy.

@ahejlsberg what do you think of this suggestion, barring any unexpected outcome?

@JsonFreeman JsonFreeman added the Spec Issues related to the TypeScript language specification label Apr 14, 2015
@JsonFreeman JsonFreeman removed the Spec Issues related to the TypeScript language specification label Apr 15, 2015
@mhegazy mhegazy added the Fixed A PR has been merged for this issue label Apr 15, 2015
@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants