简体   繁体   中英

Flow - maybe types incompatible with seemingly valid default object parameters

Consider the code:

// @flow
type Params = {
  value: ?number,
}
function acceptsMaybeNumber({

  // Error:(6, 3) null or undefined [1] is incompatible with number [2].
  // value = 4 // <--- DOESN'T WORK

  // Error:(7, 3) null or undefined [1] is incompatible with number [2].
  // Error:(7, 11) null [1] is incompatible with number [2].
  // value = null // <--- DOESN'T WORK

  // Error:(15, 3) null or undefined [1] is incompatible with number [2].
  // Error:(16, 11) undefined [1] is incompatible with number [2].
  // value = undefined // <--- DOESN'T WORK

  value // <-- WORKS
}: Params) {
  console.log(value);
}

Since the value key in Params type accepts number , null , and undefined types, setting the default value of this key to either of those should be valid but instead throws the below errors.

Why does this happen?

It's a bug in flow. https://github.com/facebook/flow/issues/183#issuecomment-358607052 . Easiest fix is probably to just not rely on the default destructuring value. So something like

type Params = {
  value?: ?number,
}
function acceptsMaybeNumber(params: Params) {
  const value = typeof params.value === 'number' ? params.value : 4
  console.log(value);
}

As noted by @TLadd, it does appear to be a bug .

The problem is specifically with using null as a permitted type when object destructuring with a default value.

$FlowFixMe can be used to suppress the error, to avoid mangling your code, or you could create your own suppression eg $FlowDestructuringDefaultBug . NB: You need to put the $Flow suppression comment on the line immediately preceding the default assignment, so you need to break your parameters across multiple lines as you did in your original example.

Here are some alternatives which might fit your use case ( Try ):

// @flow
type MaybeParams = {
  value: ?number,
}
function acceptsMaybeNumber({
  // originalValue = 1  // FAIL
  // $FlowFixMe
  value = 1,            // PASS (but not in Try where $FlowFixMe is disabled)
}: MaybeParams) {
  console.log(value);
}

type OptionalParams = {
  value?: number,
}
function acceptsOptionalNumber({
  value = 1,                // PASS
}: OptionalParams) {
  console.log(value);
}

acceptsOptionalNumber({ })  // PASS


type UndefinedParams = {
  value: void | number,
}
function acceptsUndefinedNumber({
  value = 1,                // PASS
}: UndefinedParams) {
  console.log(value);
}

acceptsUndefinedNumber({ value: undefined })    // PASS

If you specifically want to handle null as a permitted, specified value, then you'll have to avoid the default value assignment in the destructuring.

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