Something like .lax, but return nil instead of input

So there have been a few times where it would be nice to simply nullify a value if a type is invalid. Imagine we have this type:

EmailAddress ||= begin
  Types::String
    .constructor(&:downcase)
    .constructor(&:strip)
    .constrained(format: URI::MailTo::EMAIL_REGEXP)
end

Currently, you can use .lax to rescue and return the input: EmailAddress.lax.call('bad') #=> bad

This is useful, but it would be much more useful to be able to nil out the value. This would make it much easier to filter our junky data that’s is not business critical.

Something like:

EmailAddress.lax(nil: true).call('bad') #=> nil`

Would y’all be open to adding this?

This could be considered but somebody would have to take a really close look at what kind of an impact adding nil: option would have on the rest of the built-in types, as well as usage in other libraries, especially dry-schema. I’m not saying it would cause problems, it’s just that I can’t promise it won’t that’s why it would have to be investigated first.

I suspect a safer option would be a dedicated type built on top of lax type, that would simply return nil if the underlying lax type returns the original input.

Agree @solnic. What should we call it? nillable? or_nil? Something else?

@ianks I like .or_nil because Types::String.constrained(format: /\d+/).or_nil looks really sweet :slightly_smiling_face:

https://github.com/dry-rb/dry-types/pull/409 :smiley:

Oh, sorry, I missed the email from discourse. Pls hold on for a moment because I think I have a nice plan for this feature.

  • I want to avoid extending the AST above the minimum.
  • It’s a special case of https://github.com/dry-rb/dry-types/issues/407
  • Which is in order a special case of the so-called “wrapper” type.
    Types::EmailAddress.wrap { |input, type| type.input { nil } }
    
  • It’s not as nearly nice as .or_nil but we can have a syntax extension for commonly used constructors. It’s a nice thing to have.
  • I already have a POC (https://github.com/dry-rb/dry-types/compare/wrapper-type) but I’m working on a different implementation atm. I’ll try to wrap it up tonight or tomorrow morning (pun not intended). Once I get it done I’ll play with syntax extensions and we’ll see if we kill all the creatures with this boulder. :slight_smile:

My progress on this https://github.com/dry-rb/dry-types/pull/410