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

validation method like isString doesn't work when used in other methods having mixed arguments #7318

Closed
phoenisx opened this issue Jan 5, 2019 · 3 comments

Comments

@phoenisx
Copy link

phoenisx commented Jan 5, 2019

Issue Code Example on /try

const isString = (string: mixed) => typeof string === 'string' || string instanceof String;

type Custom = {
  val: string,
};

const getCustom = (string: string): Custom => { return { val: string } }


function foo(x: string | Custom): Custom {
  const obj = isString(x) ? getCustom(x) : x;
  return obj;
}

foo() method above throws flow-type compilation errors Cannot call getCustom with x bound to string because Custom [1] is incompatible with string [2], though isString method validates x before any conversions

Above code works fine, if I replace isString(x), with it's definition:

// Works
function foo(x: string | Custom): Custom {
  const obj = typeof x === 'string' ? getCustom(x) : x;
  return obj;
}
@lll000111
Copy link
Contributor

lll000111 commented Jan 6, 2019

Flow Try hat works

function isString (thing: mixed): boolean %checks {
    return typeof thing === 'string';
}

Even using this special %checks keyword — of which you can learn if you search the issues (also closed ones), still undocumented but it seems you can rely on it to be a stable feature anyway — Flow only understands some constructs as type refinements but not others. I think arrow functions won't work. There is one trick you can use: In addition to the actual JS code you can just declare a function of the same name, in the example I use Flow comment syntax to do it inline in the JS file and not in a library file:

/*::
declare function isString(x: mixed): boolean %checks(typeof x === "string");
*/

Anther trick or hack that you can do is to write actual JS code, e.g. a function, in that Flow comment style. Flow will parse it as if it's part of the code, but the JS runtime will of course ignore it, since it's a comment. This feature can be used for all kinds of tricks (to get Flow to understand something), your imagination is the limit, without polluting your actual executable code..

Here's a Flow Try illustrating the declare solution.

Note that I have to use a function if I have that declare, if I use a variable I get a name conflict. Just a minor point and limitation. As you can see it now works without the %checks on the actual function, because Flow uses the definition it finds in the declare statement.

@phoenisx
Copy link
Author

phoenisx commented Jan 6, 2019

Thanks a lot @lll000111.

I did try to search open/closed issues (even googled it) before raising this issue, but I missed proper keywords for my search, thus couldn't find any solutions. I guess, it would be fine, if I raise a PR updating the docs related to function declares ?

Found that this feature is Documented as Predicate Functions, related to #4723

@phoenisx phoenisx closed this as completed Jan 6, 2019
@lll000111
Copy link
Contributor

The docs don't mention the Flow comment syntax or thedeclare hacks though. That's all stuff I only found by frequently reading issues and the responses.

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

No branches or pull requests

2 participants