maybe icon indicating copy to clipboard operation
maybe copied to clipboard

Explicitly returning null in .map()

Open benadamstyles opened this issue 8 years ago • 7 comments

I am using maybe in React Native, in the props of a custom text component. The custom component should set the underlying Text component prop numberOfLines to 1 by default, or null if the user passes false into the custom component's truncate prop:

<BasicText
  numberOfLines={maybe(props.truncate)
    .filter(t => !t)
    .map(() => null)
    .orJust(1)}
/>

However, flow understandably complains about returning null in .map():

null (This type is incompatible with union: number | boolean | string | object type | array type
See also: call of method `map`

Is there an "idiomatic" way to handle this, or is it simply a case of putting an // $ExpectError comment and forgetting about it?

benadamstyles avatar Jun 20 '17 10:06 benadamstyles

Why would truncate false set numberOfLines to null? Should it be the other way around?

alexanderjarvis avatar Jun 20 '17 14:06 alexanderjarvis

Thanks for getting back so quickly. I probably should have used a less convoluted example! truncate: false should set it to null because null is the only way I know of making a react prop "have no effect". When numberOfLines is set to null, it doesn't do any truncating. If it's set to 1, then ellipsizeMode comes into force.

But basically what I mean is: there are some situations where we might need to return null. Is there a good way to do that?

benadamstyles avatar Jun 20 '17 14:06 benadamstyles

Put another way: we are allowed to do .orJust(null) My use case above is really just the inverse of that, but the flowtyping won't allow it.

benadamstyles avatar Jun 20 '17 14:06 benadamstyles

You need to use flatmap and return nothing.

map doesn't allow you to return a nil value and doesn't implicitly convert null to nothing. It's expected behaviour - I thought through this use case and tested other languages to compare. The problem with allowing null inside Maybe is that you will then need to check or wrap it again which kind of defeats the purpose.

On 20 Jun 2017, at 15:28, Ben Styles [email protected] wrote:

Put another way: we are allowed to do .orJust(null) My use case above is really just the inverse of that, but the flowtyping won't allow it.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

alexanderjarvis avatar Jun 20 '17 17:06 alexanderjarvis

Ok, I guess I can't use maybe for this. Just to be clear though, I can't use flatmap and return nothing because that would trigger the .orJust(1) whereas I explicitly want to return null. I'm not asking maybe to implicitly convert null to nothing.

I guess treating null as a value in this way goes directly against the concept of this lib. I don't suppose there would be a way to wrap it or something to appease flow?

benadamstyles avatar Jun 20 '17 17:06 benadamstyles

Would this work?

maybe(props.truncate).filter(t => t).map(t => 1).orJust()

I think you can return undefined for numberOfLines.

This lets you:

  1. optionally provide truncate
  2. if truncate is true then it returns 1
  3. if truncate is missing or false, it returns undefined

The vanilla equivalent is:

props.truncate && 1

which to be honest, is much simpler, if you're ok with undefined.

alexanderjarvis avatar Jun 20 '17 19:06 alexanderjarvis

The problem is the default should be 1, not null or undefined. The vanilla equivalent is:

props.truncate == null ? 1 : (props.truncate ? 1 : null)

...which is why I wanted to use maybe!

benadamstyles avatar Jun 20 '17 19:06 benadamstyles