ShakMR
ShakMR

Reputation: 115

What's the correct Flow type pattern when calling different functions depending on the type of a variable?

I'm kind of new to Flow and changing from "do whatever you like with the code" style in javascript to the more strict typing Flow forces you is a pain sometimes.

I have a class with a function returning the following:

const { id: idParam, params } = this.config[tag];
return params.map((param: string | ObjectConfigParam) => {
  const paramType = typeof param;
  let ret = { id: element.id, tag, position };
  if (paramType === 'string') {
    ret = { ...ret, ...this.resolveStringParam(element, param) };
  } else if (paramType === 'object') {
    ret = { ...ret, ...this.resolveObjectParam(element, param) };
  }
  return ret;
})

As params can be two different things (a simple string or a more complex ObjectConfigParam) I've defined to different functions to process them. The signature of the functions are:

resolveStringParam(element: any, param: string): Field

resolveObjectParam(element: any, param: ObjectConfigParam): Field

Running the flow checker reports the following error: Cannot call this.resolveStringParam with param bound to param because ObjectConfigParam [1] is incompatible with string [2]. for the first call and Cannot call this.resolveObjectParam with param bound to param because string [1] is incompatible with ObjectConfigParam [2]. for the second one.

Upvotes: 1

Views: 40

Answers (1)

Alex Savin
Alex Savin

Reputation: 528

You need to place typeof param inside the if condition. By the way, you don't need the second if.

https://flow.org/try/#0PQKgBAAgZgNg9gdzCYAoVAXAngBwKZgDyARgFZ4DGGAwnAHZQCWA5gAoCGATuwLZgC8YAN5gAznB54AauxgBXPAC4xGTozrMwAXwDc6VFDl0qjemE55xMAG54AyqvVsuvABSjVyj2o0BKYVoGRiZmFla2JORUHNw8rnBkypGUNPRMzrH+QoGoFPQeYAAeAmCuOC48Xo4aYAA+RGQptAwsMbz+-AB8wqhgYIxQpdj4cIPlsQL8ggDk3k7TWb195pZwNvbVGW7j7Xp9WmB4MKIEQkt9YWsRjdEVZRW+e9qoWkA

type ObjectConfigParam = { someValue: string };

function resolveStringParam(str: string) {}
function resolveObjectParam(obj: ObjectConfigParam) {}

const x = (param: string | ObjectConfigParam) => {
  if (typeof param === 'string') {
    resolveStringParam(param);
  } else {
    resolveObjectParam(param);
  }
}

Upvotes: 1

Related Questions