Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does intersection type for functions accept either of type declarations not both?

I took the example

/* @flow */
class Foo {}
class Bar {}
declare var f: ((x: Foo) => void) & ((x: Bar) => void);
f(new Foo());

from the documentation page https://flowtype.org/docs/union-intersection-types.html#_

And this code type checks without errors.

For me the result is not immediately obvious.

As they show somewhere near the top of the page with another example:

/* @flow */
type I = {a: number} & {b: number};
var x: I = {a: 1, b: 2};
x = {a: 1, b: 2, c: "three"};

the intersection (which flows from the term semantics itself) is the compound of 2 (or more) types. Basically AND of those.

So, why does the f(new Foo()); not fail the type check then? The new Foo() argument is clearly not an instance of the Bar so must not pass.

What am I missing?

UPD

After some more research I have found that the meaning of | and & swaps when you use declare var (versus type or in-place typing). I cannot find an explanation why it even happens in the very first place though.

like image 483
zerkms Avatar asked Oct 30 '22 13:10

zerkms


1 Answers

I may be misunderstanding your question, but I would expect it to typecheck. The argument, new Foo(), has type Foo, so the application should be ok as long as f has type Foo => .... It does. (It also has type Bar => ...).

For comparison, if f had type (x: Foo & Bar) => void, things wouldn't typecheck, because new Foo, while certainly of type Foo, is not also of type Bar.

For another comparison, if f had type ((x: Foo) => void) | ((x: Bar) => void), things wouldn't typecheck. The argument, new Foo, has type Foo, and although f might have type Foo => void, it might instead have type Bar => void.

like image 103
Alan O'Donnell Avatar answered Nov 15 '22 04:11

Alan O'Donnell