AndyH AndyH - 22 days ago 6
Perl Question

Moose: type libraries (MooseX::Types)

I am trying to figure out the proper way to incorporate Moose in my project. Here I found an article suggesting that Moose types should be organized in type libraries, which seems like a good idea. So I wrote the following code basing on the provided example:

file 1: MyTypeLib.pm

package MyTypeLib;
use MooseX::Types -declare => [ qw( MyStatus ) ];
use MooseX::Types::Moose qw/Int/;

subtype MyStatus,
as Int,
where { $_ >= 0 && $_ < 10 },
message { "Wrong status: $_" };

1;


file 2: MyTest.pm

package MyTest;
use MyTypeLib qw( MyStatus );
use Moose;

has status => ( is => 'rw', isa => 'MyStatus' );

no Moose; 1;


file 3: MyMain.pl

use strict;
use warnings;
use MyTest;

my $t1 = MyTest->new('status' => 5);


When I run it I get this message:


Attribute (status) does not pass the type constraint because:
Validation failed for 'MyStatus' with value 5 (not isa MyStatus) at
C:\Strawberry\perl\vendor\lib\Moose\Object.pm line 24


When I keep subtype definition in MyTest.pm and don't use MooseX::Types, everything works as expected. But the point is to move subtypes to a separate package and use them in other packages.
Could someone please advise how to make it work, or point to (or post) some working example, or suggest the alternative way of achieving the goal.

Thank you!

Answer

Remove the quotes: isa => MyStatus, not isa => 'MyStatus'. MyStatus is a constant-like function exported from your type library. Providing a string rather than a proper type constraint for isa ("stringy types") causes it to be looked up in Moose's type registry, or, if it's not found there, it's interpreted as the name of a class, and the type is inferred to be "any object of that class or its subclasses". Stringy types are less explicit and less flexible than using actual types, and more prone to conflicts since they all share a global namespace. It's best not to use them and type lbraries at the same time.