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

function overloading #60

Closed
fdecampredon opened this issue Nov 19, 2014 · 12 comments
Closed

function overloading #60

fdecampredon opened this issue Nov 19, 2014 · 12 comments
Labels

Comments

@fdecampredon
Copy link

I would like to express a function with the following overloading:

<B>(func: () => B): () => Promise<B>;
<A,B>(func: (a:A) => B): (a: A) => Promise<B>;

it seems to me that it is not possible since :

<A,B>(func: () => B | (a:A) => B): () => Promise<B> |  (a: A) => Promise<B>;

Does not conditionally constraint the return type, any idea ?

@avikchaudhuri
Copy link
Contributor

You can try intersection types. See an example at: http://flowtype.org/docs/union-intersection-types.html#_

@gabelevi
Copy link
Contributor

It's also worth noting that you might need to use parentheses to express the union or intersection of two function types.

  var a : () => A | B

is parsed as

var a : () => (A | B)

so the union of two functions is

var a : (() => A) | () => B

@fdecampredon
Copy link
Author

Thanks.
However if you wish to support .d.ts files anyways I guess flow will need to be able to consume typescript overloading style.

@avikchaudhuri
Copy link
Contributor

No doubt. Currently we do support overloading syntax, at least in some contexts. For example, you can write:

declare class C {
foo(x: number): number;
foo(x: string): string;
}

@avikchaudhuri
Copy link
Contributor

The following should now work, closing.

declare function foo<B>(func: () => B): () => Promise<B>;
declare function foo<A,B>(func: (a:A) => B): (a: A) => Promise<B>;

foo(() => 0)(); // OK
foo((x: number) => "")(); // error: too few args, undefined ~/~ number

@leoasis
Copy link

leoasis commented Jul 29, 2015

Is it possible to set overloading types for function without using declare?

jeffmo added a commit to jeffmo/flow that referenced this issue Jul 31, 2015
Support rest parameter type annotations
@Macil
Copy link
Contributor

Macil commented Feb 24, 2017

@avikchaudhuri Is there a way to do that while also defining the function?

@pronebird
Copy link

pronebird commented Jul 28, 2017

It does not work in other contexts as @leoasis pointed out. such as when defining a function. Flow is not able to select the right combo.

// @flow

type State = Array<number>;
type GetState = () => State;

type Action = { type: 'A' };
type Thunk = (dispatch: Dispatch, getState: GetState) => Promise<any>;

type Dispatch = ((action: Action) => Action) | ((action: Thunk) => Promise<any>);

const dispatch: Dispatch = (action) => {
  if(typeof action === 'function') {
    return action(dispatch, () => { return [1]; });
  }
  return action;
}

dispatch({ type: 'A' });
dispatch((dispatch, getState) => Promise.resolve());

Throws the following error:

9: type Dispatch = ((action: Action) => Action) | ((action: Thunk) => Promise<any>);
                                                            ^ function type. Callable signature not found in
18: dispatch({ type: 'A' });
             ^ object literal

11: const dispatch: Dispatch = (action) => {                               
                               ^ function. Could not decide which case to select
11: const dispatch: Dispatch = (action) => {
                    ^ union type

9: type Dispatch = ((action: Action) => Action) | ((action: Thunk) => Promise<any>);
                             ^ property `type` of object type. Property not found in
19: dispatch((dispatch, getState) => {             
             ^ function

@hackhat
Copy link

hackhat commented Aug 3, 2017

// @flow

const items = [1, 2, 3];

type FirstType = ((_: 'a') => number) & ((n: 'b') => Array<number>);

const first: FirstType = (n):any => {
  if (n === "a") {
    return items[0];
  } else if(n === 'b') {
    return items;
  }
}

const a: number = first('a');
const b: Array<number> = first('b');

Is partially working. From https://stackoverflow.com/questions/45481046/how-to-define-a-type-of-return-based-on-an-argument-string-flowtype-javascript

@morajabi
Copy link

morajabi commented Sep 4, 2017

Any progress here? I think it's a quite important feature.

@zeorin
Copy link

zeorin commented Jul 11, 2018

Interfaces seem to have the behaviour you're looking for: #3021 (comment).

@lll000111
Copy link
Contributor

lll000111 commented Jul 16, 2018

@zeorin Your linked example does not show how one would define a function. I'm not quite sure what it does, actually, there doesn't seem to be any Javascript, just Flow type stuff. How would one use that to do something real, with JS code? You define the function XYZ, how do you annotate it to have multiple type signatures? If you follow my linked issue, I link to examples hat use an intersection type of function signatures, but that doesn't seem to work when I introduce generics, or I don't know how to do that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants