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

Intersection of function types #20414

Closed
jishi9 opened this issue Dec 3, 2017 · 3 comments
Closed

Intersection of function types #20414

jishi9 opened this issue Dec 3, 2017 · 3 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@jishi9
Copy link

jishi9 commented Dec 3, 2017

TypeScript Version: 2.7.0-dev.201xxxxx

Code

class Foo {
    foo(): number {
        return 3;
    }
}

const x:
    { foo: (() => number) | (() => string) }
    & { foo: (() => number) } = new Foo();

const value: number = x.foo();

Expected behavior:
Compiles, because the (A|B) & A == A

Actual behavior:
Assignment to 'value' fails with:
Type 'string | number' is not assignable to type 'number'.

Background
Aside being a correctness issue, the motivation here is to enable type guards which narrow the return type of a function:

interface Producer {
    onlyMakesNumber(): this is {makeThing: () => number};

    makeThing(): string|number;
}

interface NumberProducer extends Producer {
  makeThing(): number;
}

function produceNumber(p: Producer) {
  if (p.onlyMakesNumber()) {
    const x: number = p.makeThing();  // compile error.

    const p2: NumberProducer = p;
    const y: number = p2.makeThing();  // compiles.
  }
}
@jcalz
Copy link
Contributor

jcalz commented Dec 3, 2017

You expect the TypeScript compiler to implement the absorption laws, but it doesn't. There's also a wrinkle here that intersection of function types are interpreted as overloads, so that could possibly complicate how absorption would work with function types. 🤷‍♂️

@DanielRosenwasser
Copy link
Member

Like @jcalz said, (A | B) & A is actually A | (A & B), and intersections of object types don't obliterate each other to never - they're purely additive.

@DanielRosenwasser DanielRosenwasser added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jan 2, 2018
@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
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

4 participants