I moved the boolean "if" condition into a function because it was pretty long. Without any other changes, this if-condition type guard is no longer recognized and Flow complains about using properties that that function checks exist.
After some experiments, I don't see a way to have a type guard be a function?
I understand the "mutability" assumption Flow makes whenever a function is called, but being unable to use a function as type guard, as seems to be the case, seems a little... severe. After all, functions starting with is...() (isBoolean, isThis, isThat, etc.) are quite common. I am unable to use a function in a type guard check?
// @flow
'use strict';
function test1 () {
// ERROR: Property 'myFn' cannot be assigned on 'data' (mixed)
function isMyFunction (data: mixed): boolean {
return typeof data === 'object' && data !== null && data.myFn === 'function';
}
function demo (data: mixed): void {
if (isMyFunction(data)) {
data.myFn = () => {
// ...
};
}
}
}
function test2 () {
// WORKS
function demo (data: mixed): void {
if (typeof data === 'object' && data !== null && data.myFn === 'function') {
data.myFn = () => {
// ...
};
}
}
}
Error: src/main.js:11
11: data.myFn = () => {
^^^^ property `myFn`. Property cannot be assigned on
11: data.myFn = () => {
^^^^ mixed
Found 1 error
Add %checks to your function annotation:
function isMyFunction (data: mixed): boolean %checks {
This leads to a question and a problem:
Question: Is this documented somewhere?
Problem: Since I'm not the only one who has never heard of that annotation Webstorm goes berserk (and all yellowish "I don't recognize what you are writing" background). Which leads back to the question - I don't want to file a Webstorm ticket for a feature that isn't documented.
I agree it should be documented, but to work around your problem you can do this:
```js
function isMyFunction (data: mixed)/*: boolean %checks */{
@vkurchatkin I changed the title, would you please reopen the issue and label it "documentation"? I think that's better than me opening another issue.
Could somebody tell me if %checks is official enough to open a Webstorm ticket to add this to the accepted syntax? Or is this just a workaround that some day may disappear.
UPDATE:
The check does not work when I move it into another file (module) and require() it from there. The exact same function!!
It's expected. Only type annotations passes through files. This makes flow fast. Passing additional information with %checks can solve the problem, but this is not implemented yet.
@TrySound There is a problem - so I opened an issue.
@TrySound I read that yesterday. I searched for "%checked" in the issues list. I refrained from linking it because it isn't about %checks in particular. I tried to limit the scope of my issue to that concrete item, since as you correctly point out there already is one for more general discussion.
Link: #4900 ‘When annotating with %checks I don't get an expected error from a type checking function’ was the issue that @lll000111 mentioned opening.
@panagosg7 since you implemented this could you tell me how I would use %checks in a library definition? From the playground, looks like it's not possible at the moment. Could it be?
e.g.
declare module "lodash" {
declare class Lodash {
isString: (value: any): boolean %checks (typeof value === 'string');
}
declare var exports: Lodash;
}
function method(x: string | number): number {
if (lodash.isString(x)) {
return x.charCodeAt(0);
} else {
return x;
}
}
I'm afraid function predicates (and the use of %checks modifier) are not supported for class methods at the moment.
@Whoaa512 if import the check function by name:
import {isString} from 'lodash';
function method(x: string | number): number {
if (isString(x)) { .... }
}
It works for me.
@loyd Is that using the flow-typed declarations? or a custom one you wrote? Could you share that it looks like?
@Whoaa512
I have tried not with lodash, but the same case:
Declaration
Import
Usage
Thanks, my mistake =(
Do predicate functions work with instanceof I'm trying to implement a simple error handler with no luck frowtry. Or am I missing something else?
Hi @maxmalov! instanceof works. The problem in the above is the property access. Flow cannot refine properties of objects in predicate functions. Here's a workaround: try-flow
Checks is documented here.
I'm afraid function predicates (and the use of %checks modifier) are not supported for class methods at the moment.
@panagosg7 Do you know if function predicates support was added for class methods?
@akoppela No, class methods are still not supported.
Most helpful comment
UPDATE:
The check does not work when I move it into another file (module) and
require()it from there. The exact same function!!