Type::Tiny Tricks #5: Wrapping Moose/Mouse Type Constraints

This is a very old article. It has been imported from older blogging software, and the formatting, images, etc may have been lost. Some links may be broken. Some of the information may no longer be correct. Opinions expressed in this article may no longer be held.

So you have this Moo class, and it turns out what you really need for it is the StrictVersionStr type constraint defined in MooseX::Types::Perl. You could switch the class to Moose, but long term you want to stick with Moo.

Eventually you’ll steal what you need from MooseX::Types::Perl, so you don’t have the Moose dependency, but for now what you really want is to be able to use a Moose type constraint within a Moo class! What a predicament you’ve gotten yourself into! Type::Tiny to the rescue!

   {
      package Local::Eg5;
      use Moo;
      use MooseX::Types::Perl qw( StrictVersionStr );
      use Types::TypeTiny qw( to_TypeTiny );
      
      has version_number => (
         is   => "ro",
         isa  => to_TypeTiny( StrictVersionStr ),
      );
   }

to_TypeTiny converts a MooseX::Types type constraint, or a MouseX::Types type constraint into a Type::Tiny one, making it safe to use in Moose, Mouse, Moo, or anywhere else that accepts Type::Tiny objects. It converts any coercions attached to the type; it even handles inlining.

to_TypeTiny is also able to convert a coderef to a Type::Tiny object. The coderef is expected to return true if the value passes the type constraint, and either return false or die with a helpful error message if it fails.

   to_TypeTiny(sub { $_ % 2 == 0 or die "not even!" })

to_TypeTiny is used internally by Type::Tiny pretty much everywhere a type constraint would be accepted. So, for example, the Types::Standard ArrayRef type constraint can be parameterized with the MooseX::Types-based StrictVersionStr type:

   {
      package Local::Eg5
      use Moo;
      use MooseX::Types::Perl qw( StrictVersionStr );
      use Types::Standard qw( ArrayRef );
      
      has version_numbers => (
         is   => "ro",
         isa  => ArrayRef[StrictVersionStr],
      );
   }

Similarly, a union type like HashRef|StrictVersionStr should “just work”.