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 ?
You can try intersection types. See an example at: http://flowtype.org/docs/union-intersection-types.html#_
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
Thanks.
However if you wish to support .d.ts files anyways I guess flow will need to be able to consume typescript overloading style.
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;
}
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
Is it possible to set overloading types for function without using declare
?
@avikchaudhuri Is there a way to do that while also defining the function?
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
// @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
Any progress here? I think it's a quite important feature.
Interfaces seem to have the behaviour you're looking for: https://github.com/facebook/flow/issues/3021#issuecomment-404156975.
@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.
Most helpful comment
Is it possible to set overloading types for function without using
declare
?