Skip to content
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

Functions with intersection arguments are not always typed coherently #9514

Closed
Elephant-Vessel opened this issue Jul 5, 2016 · 3 comments
Closed
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Fixed A PR has been merged for this issue

Comments

@Elephant-Vessel
Copy link

Elephant-Vessel commented Jul 5, 2016

TypeScript Version: 1.8.10

Code

// tl;dr: 
// This should give a static error, but does not.
var monkeyAnalyzer: (input: Monkey) => void = (input: Monkey & Robot) => { console.log(input.FurColor, input.MotorCount); }
// Will definitely fail, as we can expect from the incompatible signatures of the declared type of monkeyAnalyzer and what we actually assign to it
monkeyAnalyzer(new Monkey()); 

// Verbose example
class Monkey
{
    public FurColor: string;
}

class Robot
{
    public MotorCount: number;
}

class MonkeyRobotAnalyzer
{
    public static Analyze = (input: Monkey & Robot): void =>
    {
        console.log(input.FurColor, input.MotorCount);
    }
}

class MonkeyManager
{
    constructor(monkeyAnalyzer: (input: Monkey) => void)
    {
        monkeyAnalyzer(new Monkey());
    }
}

MonkeyRobotAnalyzer.Analyze(new Monkey()); // Shows error as it should

var myManager = new MonkeyManager(MonkeyRobotAnalyzer.Analyze); // No error, but should not be allowed, signature of MonkeyRobotAnalyzer.Analyze is not compatible with (input: Monkey) => void

Expected behavior:

The incompatible signatures should result in a static error

Actual behavior:
We get no static error

@HerringtonDarkholme
Copy link
Contributor

HerringtonDarkholme commented Jul 5, 2016

This is a by-design behavior because of bivariant function, as stated in FAQ

When comparing the types of function parameters, assignment succeeds if either the source parameter is assignable to the target parameter, or vice versa.

Here you are using (input: Monkey & Robot) => void as (input: Monkey) => void, and the latter is assignable to the former. So the function call just type checks.

@Elephant-Vessel
Copy link
Author

Elephant-Vessel commented Jul 5, 2016

Oh my, would it be possible to get this as a compiler flag? This led to a lot of code being faulty and in need of refactoring in a system I'm working on due to a minor mistake in the type declaration of an input parameter.

It seems that the motivation for this behavior is to enable useful hacks at the cost of type safety. Isn't typescript all (well mostly) about the opposite? A small compiler flag at least? Pretty please?

@HerringtonDarkholme
Copy link
Contributor

Please see this discussion.

#1394

@mhegazy mhegazy added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Jul 6, 2016
@mhegazy mhegazy closed this as completed Sep 20, 2016
@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label Sep 21, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

4 participants