简体   繁体   中英

Flow Type: difference between “optional function parameters” and “maybe types”

Can someone please explain the difference between "optional function parameters" and "maybe types", as explained on on this page of the Flow documentation?

The definitions sound very similar:

Maybe types: "Maybe types are for places where a value is optional"

Optional function parameters: "Functions can have optional parameters where a question mark ? comes after the parameter name."

I understand the differences from a syntax perspective. However, it sounds like both would be used in situations where you want to define an optional parameter for a function. Where would you use one over the other?

There isn't a difference. But also they're totally different things.

I think there's a bit of conceptual confusion here. Here's an example of an optional parameter:

function recase(str, lower) {
  if (lower) {
    return str.toLowerCase();
  }

  return str.toUpperCase();
}

recase('Test', true)
// "test"
recase('test')
// "TEST"
recase()
// Uncaught TypeError: Cannot read property 'toUpperCase' of undefined

Our function takes two arguments. The first one is required, if we don't pass at least one argument, the function will throw an exception. The second one is optional, if we don't pass the second one then no exception will be thrown, the value returned will just be different.

Note that I haven't introduced any types. This is because an "optional parameter" here is just a general programming concept. Flow doesn't have some intrinsic feature called "optional parameters." What flow does offer is a way to type optional parameters, called "maybe types."

So say I want to type my function above. Well, a first pass might look like this:

// We're taking a string and a boolean and returning a string, right?
function recase(str: string, lower: boolean): string {
  if (lower) {
    return str.toLowerCase();
  }

  return str.toUpperCase();
}

recase('Test', false)
// "TEST"
recase('Test', true)
// "test"
recase('Test')
// ^ Cannot call `recase` because function [1] requires another argument.

Since we typed lower as boolean , flow is expecting a boolean to be passed as the second argument. When we don't pass a boolean, flow throws an error. Our parameter is no longer optional. We could just remove the type from lower , but then flow would default lower to the any type, meaning the user could pass whatever they wanted which makes our types ambiguous and error-prone. Here's one thing we could do:

function recase(str: string, lower: void | boolean): string {
  if (lower) {
    return str.toLowerCase();
  }

  return str.toUpperCase();
}

recase('Test', true)
// "test"
recase('Test')
// "TEST"

In flow, the void type only matches a value of undefined . If we do not provide a value for lower when calling recase , then the value of lower will be undefined , and by typing lower as void | boolean void | boolean we have told flow that lower can be either a boolean or undefined (not specified as a parameter).

So this is a very common scenario, obviously. So common in fact that at some point we might consider encapsulating it. This could be done with generics, like so:

// Let's call this Q for "Question" but it's nice and short
type Q<T> = void | null | T;

function recase(str: string, lower: Q<boolean>): string {
  if (lower) {
    return str.toLowerCase();
  }

  return str.toUpperCase();
}

Note that we've added null to our generic type because the undefined case overlaps so much with the null case of wanting to be able to pass in null for optional parameters.

Well, this is so common that flow offers us what amounts to a syntactic sugar for this situation, called "maybe types." If you were able to rename our Q type to ? then you would basically have maybe types.

function recase(str: string, lower: ?boolean): string {
  if (lower) {
    return str.toLowerCase();
  }

  return str.toUpperCase();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM