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".