Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Flow understand dynamic code that uses lodash for runtime type-checking?

Tags:

flowtype

Flow's dynamic code example indicates that Flow can figure out runtime type-checking:

function foo(x) {
  if (typeof x === 'string') {
    return x.length; // flow is smart enough to see this is safe
  } else {
    return x;
  }
}

var res = foo('Hello') + foo(42);

But in real life, typeof isn't good enough. I usually use lodash's type-checking functions (_.isFunction, _.isString etc), which handle a lot of edge cases.

The problem is, if we change the example to use lodash for the runtime type-checking, Flow no longer understands it:

function foo(x) {
  if (_.isString(x)) {
    return x.length; // warning: `length` property not found in Number
  } else {
    return x;
  }
}

var res = foo('Hello') + foo(42);

I tried using iflow-lodash but it doesn't seem to make a difference here.

What's the best solution to make Flow understand code that uses lodash for runtime type-checking? I'm new to Flow btw.

like image 434
callum Avatar asked Dec 06 '22 16:12

callum


1 Answers

This would depend on having predicate types in your lodash libdefs.

Predicate types have recently been added to Flow. Although they are still in an experimental state so I would recommend being careful about their usage for anything serious for now.

function isString(x): boolean %checks { // << declare that the method is a refinement
  return typeof x === 'string';
}

function method(x: string | number): number {
  if (isString(x)) { // << valid refinement
    return x.charCodeAt(0); // << no errors
  } else {
    return x;
  }
}

[try it out]

Note: This answer may quickly fall out of date in one of the next releases as this is a brand new feature. Check out Flow's changelog for the latest information.

The solution for now if possible is to use the built-in refinements.

function method(x: string | number): number {
  if (typeof x === "string") { // << Inline the check
    return x.charCodeAt(0);
  } else {
    return x;
  }
}
like image 73
James Kyle Avatar answered May 16 '23 06:05

James Kyle