How to convert all object properties (function) to async functions in flowtype? - flowtype

Given an object type that has functions as values I need to create object types with similar structure but having values as async functions.
Imagine this function
function convert(foo) {
return async function(...args) {
return foo(...args)
}
}
Applied to values of this type
type Source = {
foo: number => string,
bar: string => number
}
So I get this type
type Result = {
foo: number => Promise<string>,
bar: string => Promise<number>
}
Is it possible in flow?

Related

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'TraderList'

onFetchTrader() {
this.http.get<TraderList>(this.url)
.pipe(map(resData => {
// console.log(resData);
const traderArray: any[] = [];
for (const key in resData) {
// console.log(key);
// console.log(resData[key]);
// console.log(resData.hasOwnProperty(key));
if (resData.hasOwnProperty(key)) {
// traderArray.push({clientId:key, ...resData})
traderArray.push({ clientId: key, ...resData[key] })
}
}
return traderArray;
}))
.subscribe(traders => {
// console.log(traders);
this.traders = traders;
});
I am trying to fetch the data from real time server but not able to map response data . I am getting error as Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'TraderList'.
I am trying to push the data in a array.spraed operator used ...resData[key] giving problem. Please suggest solution.

FlowJS and function with 2 signatures and optional parameter

How do I precisely type in Flow the following function that either takes a callback and call it later with some value or takes no arguments and return a Promise for that value?
const foo = callback => {
const p = Promise.resolve(1.0);
if (callback === undefined) {
return p;
}
p.then(callback);
}
};
I tried to use an intersection type like in:
type CallbackCase = ((number) => void) => void;
type PromiseCase = () => Promise<number>;
const foo: CallbackCase & PromiseCase =
callback => {
const p = Promise.resolve(1.0);
if (callback === undefined) {
return p;
}
p.then(callback);
};
But then Flow complains (this is also so with the latest version at https://flow.org/try):
Cannot assign function to `foo` because undefined [1] is incompatible with `Promise` [2] in the return value. [incompatible-type]
So how can I fix this?
Update: The reason for this signature is that we have older code where the function was taking a callback. We would like to convert it to the promise form while still supporting older callers. During the conversion we would like to keep the types precise. In particular at the call site only the two forms should be allowed:
let a: Promise<number> = foo();
foo(callback);
Any other forms should be rejected.
You can specify argument as a function
type Callback = <T>(T) => void;
const foo =
(callback:Callback) => {
const p = Promise.resolve(1.0);
if (callback === undefined) {
return p;
}
p.then(callback);
};
seems to works well

Functions for constructing Flow types?

Is there any way I can do something like this:
// #flow
function FailureActionType(name: string): Type {
return {type: name, error: string}
}
type SearchFailureAction = FailureActionType("SEARCH_FAILURE")
Obviously there's problems in the way the typing/assignments are written in the return statement, but it would work such that
type SearchFailureAction = { type: "SEARCH_FAILURE", error: string }
Is there any way to do that?
You want a generic.
type FailureActionType<T: string> = { type: T, error: string }
The <T> there says that this type is dependent on another type.
<T: string> means this dependent type must be a type of string.
{ type: T, error: string } means the resulting type must have the dependant type on the type key of the object.
You use it by passing in a value for T in <> like so:
type SearchFailureAction = FailureActionType<"SEARCH_FAILURE">
const action1: SearchFailureAction = { type: 'SEARCH_FAILURE', error: 'some error' }
const action2: SearchFailureAction = { type: 'BAD', error: 'some error' } // type error
flow.org/try Proof
Generics are pretty powerful. Read the docs for more.
https://flow.org/en/docs/types/generics/

How to type annotate "function wrappers" (function which returns a function with the same signature as it's argument)

Is there a way to properly tell flow that I'm returning a function with the same signature as the function I'm passed, but not exactly the same function ?
This is an example of a "once" wrapper which prevents a function from being called multiple times, it works but uses an any-cast internally to make flow give up, I'd like to get rid of that cast and have 100% coverage:
module.exports.once = /*::<F:Function>*/(f /*:F*/) /*:F*/ => {
let guard = false;
return ((function () {
if (guard) { return; }
guard = true;
return f.apply(null, arguments);
}/*:any*/) /*:F*/);
};
Okay, first things first.
Your return value can currently never match F without your casting through any because the signature of the function you're returning is not the same because it can return undefined where the original may not.
(comment syntax removed for readability)
module.exports.once = <F: Function>(f: F): F => {
let guard = false;
return ((function () { // this function returns the return value of F or void
if (guard) { return; } // returning void
guard = true;
return f.apply(null, arguments);
}: any): F);
};
But to start typing this, we're gonna need to break down that function generic a little bit.
First of all, let's not use Function as it's generally better if we don't:
However, if you need to opt-out of the type checker, and don’t want to go all the way to any, you can instead use Function. Function is unsafe and should be avoided.
Also, we're going to extract the types of the arguments and the return value so we can manipulate them independently and construct a return type. We'll call them Args and Return so they're easy to follow.
module.exports.once = <Args, Return, F: (...Array<Args>) => Return>(
f: F
) ((...Array<Args>) => Return | void) => { // note `Return | void`
let guard = false;
return function () {
if (guard) { return; }
guard = true;
return f.apply(null, arguments);
};
};
Now that we're taking into account that our new function might return void everything type checks fine. But of course, the return type of our once function will no longer match the type of the passed function.
type Func = (number) => string;
const func: Func = (n) => n.toString();
const onceFunc: Func = module.exports.once(func); // error!
// Cannot assign `module.exports.once(...)` to `onceFunc` because
// undefined [1] is incompatible with string [2] in the return value.
Makes sense, right?
So, let's discuss the signature of this function. We want our return value to have the same signature as the function we pass in. Currently it doesn't because we're adding void to the signature. Do we need to? Why are we returning undefined? How can we always return the same type from our onced function? Well, one option would be to store the return value from the single call to the function and always return the stored return value for subsequent calls. This would kind of make sense because the whole point is to allow multiple calls but not perform any of the functions effects. So this way we can avoid changing the interface of the function, so we really don't need to know whether or not the function has been called before.
module.exports.once = <Args, Return, F: (...Array<Args>) => Return>(
f: F
): ((...Array<Args>) => Return) => {
let guard = false;
let returnValue: Return;
return function () {
if (guard) { return returnValue; }
guard = true;
returnValue = f.apply(null, arguments);
return returnValue;
};
};
type Func = (number) => string;
const func: Func = (n) => n.toString();
const onceFunc: Func = module.exports.once2(func);
One good question to ask at this point would be, why do the types match even if we're not technically returning exactly F? The answer to that is because functions in flow are structurally typed. So if they have the same arguments and return value, their types match.

Angular2 using http.get with a distinct

I am trying to learn more about the Http.Get. I am using a json file to mock the HTTP call. After the call I want to limit the rows to unique states. I know there is an Rxjs command called distinct (help on Rxjs distinct). However I do not understand the syntax for the distinct. When I run this code as is I get an array of states. However when I add the distinct it still has duplicated states like Texas.
public getStates(): Observable<IState[]> {
return this._http.get(this.stateUrl)
.map((res: Response) => <IState[]>res.json())
// distinct by state name
.distinct((x) => return x.state)
;
}
Here is the interface for IState
export interface IState {
id: number;
state: string;
city: string;
name: string;
}
Trying to only get rows with a unique state.
I have repo for the code on this Github project
You're confusing a bit the meaning of the distinct in this situation!
This distinct is meant to filter the response from your Observable, not its content! Here you're trying to "distinct" (filter) your json object, but the distinct will filter the responses (multiple) "resolved" by the Observable. So, if the observable "resolves" the same response multiple times, you'll receive only once, because of your .distinct.
This means, if the 1st time the Observable returns you back one json (e.g [{0: a, 1:b, 2:c}]) and the second time he returns the same json reponse, then your "subscribers" will not receive it twice, because the .distinct will "filter" it and as a result it will not be fired!
more details here: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/distinct.md
So, what you're looking for, is how to "filter" duplicated results within your json.
The answer is simple: use a loop to check its properties/values or some library like underscore which might have this method already implemented.
The IState is an object. You have to define what exactly makes them distinct from each other.You can look at the documentation, there is a way to define what makes an object distinct
For example:
/* Without key selector */
var source = Rx.Observable.of(42, 24, 42, 24)
.distinct();
var subscription = source.subscribe(
function (x) {
console.log('Next: %s', x);
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
// => Next: 42
// => Next: 24
// => Completed
/* With key selector */
var source = Rx.Observable.of({value: 42}, {value: 24}, {value: 42}, {value: 24})
.distinct(function (x) { return x.value; });
var subscription = source.subscribe(
function (x) {
console.log('Next: %s', x);
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
// => Next: { value: 42 }
// => Next: { value: 24 }
// => Completed
The problem is that when you're calling .distinct((x) => return x.state) the x variable is the entire array from https://github.com/ATXGearHead12/distinct/blob/master/src/api/state.json. Then property x.state doesn't exists.
So you need to call distinct on each item in the array not on the array itself.
For example like the following:
this._http.get(this.stateUrl)
.map((res: Response) => <IState[]>res.json())
.concatMap(arr =>
Observable.from(arr).distinct((x) => return x.state)
)
.toArray(); // collect all items into an array

Resources