Why does Flow allow this unsound destructuring assignment? - flowtype

https://flow.org/try/#0PTAEAEDMBsHsHdQGcAuAnAlgYxQKC7AHaqgDaaApkgK7QoC6oAvKAN4AeAXKAIwC+AbiA
Flow reports no errors on this code:
// #flow strict
const [result] = {x: 1};
But when I try to execute it I get: Uncaught TypeError: {(intermediate value)} is not iterable.
I'm not sure if this is a bug in flow or if I'm just misunderstanding something.
Perhaps Flow is thinking the above is equivalent to
const result = {x: 1}[0];
Which I know flow intentionally allows to pass typechecking because it's an array access. In this case, result is undefined rather than a TypeError being thrown.

Related

I am trying to build a facebook clone dapp using solana and next js. I followed the tutorial but i still run into this error

I followed the tutorial yet this error isn't being solved](https://i.stack.imgur.com/2qNEF.jpg)
I tried to use {} instead of [] but still the same error occurs
your useContext return null. And you try to destructure null. If you don't provide array in context provider value then you can't write:
const [a1, a2] = ....
So probably you miss match useState
const [state, setState] = useState
with context
const context = useContext(Context)
So. Just write:
const balance = useContext(BalanceContext);
console.log('balance context:',balance)
and then you will see what is in balance context.
if is a object then you have to destructure object.
ps.
quick fix to run project:
const [balance, setBalanace] = useContext(BalanceContext) || [];
// balance and setBalance is undefined

Unable to resolve flow annotation error when using immutablejs records and calling update on one

I see the following record type code:
type AppProps = {
+fetches: Map<string, number>,
};
export const makeApp: RecordFactory<AppProps> = Immutable.Record({
fetches: Immutable.Map()
});
export type App = RecordOf<AppProps>;
Now I have a call that uses the record's update function:
const state = makeApp({});
const result = state.update('fetches', val =>
val.set(action.meta.actionBase, 1)
);
All unit tests pass, behaviour is good, but I get a flow error:
Error:(40, 18) Missing type annotation for T. T is a type
parameter declared in RecordInstance [1] and was implicitly
instantiated at call of method update [2].
I have an idea what is going on here, but I don't know flow well known to actually fix this, or even come up with a workaround. Please help!
ImmutableJS version "immutable": "^4.0.0-rc.12",
Flow is asking for a concrete type argument for T, which is defined in the update function of state.
Here's another example of a cause and fix of this error message:
Missing annotation error
Fixed
If you provide the type signature of state.update, I may be able to provide more information.

Calling an external function with redux-saga yield call appears to give context errors

I have a redux-saga watcher/saga setup as below:
function* parseSaga(action) {
let result = corewar.parser.parse(action.redcode)
yield put({ type: PARSE, result })
}
export function* parseWatcher() {
yield takeLatest(PARSE_REQUESTED, parseSaga);
}
Where corewar is an imported npm package I've written.
When the function is written as above, it works as expected, but I'd like to wrap the call to parse in a yield call so that I can better test things as described in the docs here: https://redux-saga.js.org/docs/basics/DispatchingActions.html
However, when I wrap up the function call like so:
let result = yield call(corewar.parser.parse, action.redcode)
I get an error which appears to come from my npm package as follows:
uncaught at parseWatcher at parseWatcher
at takeLatest
at parseSaga
TypeError: Cannot read property 'scanner' of null
at Parser.parse (http://localhost:3000/static/js/bundle.js:2017:28)
at runCallEffect (http://localhost:3000/static/js/bundle.js:43679:19)
at runEffect (http://localhost:3000/static/js/bundle.js:43601:648)
... and so on
Scanner in this case is an internal property to the Parser class which is called in the parse method as shown below (in typescript):
public parse(document: string, options?: IParseOptions): IParseResult {
options = Object.assign({}, Parser.DefaultOptions, options || {});
var context = this.scanner.scan(document, options);
... other stuff
}
So it appears like somehow through using this saga it's got inside my npm package and messed up the this reference?
It seems like I need to somehow ensure the previous context is retained but I wasn't sure how to achieve this as I'm not aware of how it's become lost by just wrapping the external call up in the redux-saga call function.
EDIT: The plot thickens
So it's definitely a context issue, but it seems related to calling nested function calls. I've tweaked the npm package so that parse is also exposed from the root object and now see the following results:
Works
let result = yield call(corewar.parse.bind(corewar), action.redcode)
let result = yield call([corewar, corewar.parse], action.redcode)
but the original nested method does not
Does not work
let result = yield call(corewar.parser.parse.bind(corewar), action.redcode)
let result = yield call([corewar, corewar.parser.parse], action.redcode)
I'm willing to expose the public interface from the root object (as it was on my todo list anyway) but is this the expected result? or some quirk?
Isn't this working
let result = yield call(corewar.parser.parse.bind(corewar.parser), action.redcode)
Since parse is a method of coreware.parser and not just coreware.
If this is not working then why not:
const parse = code => corewar.parser.parse(code);
let result = yield call(parse, action.redcode)

How to declare a flowtype library definition for polymorphic functions

What is the proper way to specify the type definitions a polymorphic method that depending on the parameter types has different return types?
index.js:
// #flow
import {func1} from './lib1';
const s: string = func1('string');
const b: boolean = func1(); // should cause type error but does not!
lib1.js:
export function func1(p) {
return (typeof p === 'string') ? p : 0;
}
defs/lib1.js.flow
// #flow
declare module "lib1" {
declare export function func1(p: string): string;
declare export function func1(_: void): number;
}
.flowconfig:
[libs]
defs/
I would have hoped to received an error message in index.js(4) but flow does not complain!
Yes, the example you gave is how to declare an overloaded function. However, you may want to change the second line to:
declare function myFunc(_: void): number;
Since Flow allows a function to be called with too many arguments (though not for much longer), it may select the second overload even if the function is called with a string. The modification I suggest makes it so the argument must be undefined (which is what is implicitly passed if you just leave off an argument).

Unexpected TypeError: Cannot read property 'apply' of undefined (meteor-rxjs)

I'm getting an exception and don't understand why. The sample code is cut down from the original, but the line in question starts let subscription=. This code is within a method so only occurs on the server side.
The failing line within Meteor subscribe():
return Meteor.subscribe.apply(Meteor, [name].concat(args.concat([{...
Here's the exception and traceback:
Exception while invoking method 'someMethod' TypeError: Cannot read property 'apply' of undefined
at subscribe (c:\Build\myapp\node_modules\meteor-rxjs\dist\bundles\index.umd.js:609:36)
at Observable._subscribe (c:\Build\myapp\node_modules\meteor-rxjs\dist\bundles\index.umd.js:628:30)
at ZoneOperator.call (c:\Build\myapp\node_modules\meteor-rxjs\dist\bundles\index.umd.js:695:23)
at Observable.subscribe (c:\Build\myapp\node_modules\rxjs\Observable.js:42:22)
Here's my code within a Meteor method:
let list = MyCollection.find(aselector);
let subscription= MeteorObservable.subscribe("publishedList, selector).zone().subscribe( () => {
list = MyCollection.find(selector);
let myArray = list.fetch();
let item: MyItem = myArray.length > 0? myArray[0]: null;
});
The Meteor method should not contain subscribes, since the collection operations are synchronous in the simple case (no callback). Removing the extra code that came from trying to solve the issue and ignoring edge cases, the code can be simplified to:
let item: MyItem = MyCollection.findOne(selector);

Resources