use Types::Common::Numeric qw(PositiveInt);
has user_id => (
is => 'ro',
isa => PositiveInt,
);
####
package MyApp::Types {
use Type::Library
-base,
-declare => qw(
UserId
UserIdList
);
use Type::Utils -all;
BEGIN {
extends qw(
Types::Standard
Types::Common::Numeric
Types::Common::String
);
};
declare UserId,
as PositiveInt,
where { $_ > 1000 };
declare UserIdList,
as ArrayRef[UserId];
...;
}
##
##
declare User, as InstanceOf['MyApp::User'];
coerce User,
from UserId, via { MyApp::Utils::find_user_by_id($_) };
coerce UserId,
from User, via { $_->user_id };
##
##
package MyApp::Types {
use Type::Library -base;
use Type::Utils (); # don't import any keywords
BEGIN {
# Type::Utils is still the easiest way to do this part!
Type::Utils::extends(qw(
Types::Standard
Types::Common::Numeric
Types::Common::String
));
};
my $userid = __PACKAGE__->add_type({
name => 'UserId',
parent => PositiveInt,
constraint => '$_ > 1000',
});
my $user = __PACKAGE__->add_type({
name => 'User',
parent => InstanceOf['MyApp::User'],
});
$userid->coercion->add_type_coercions(
$user => '$_->user_id'
);
$user->coercion->add_type_coercions(
$userid => 'MyApp::Utils::find_user_by_id($_)',
);
__PACKAGE__->add_type({
name => 'UserIdList',
parent => ArrayRef[$userid],
coercion => 1,
});
...;
__PACKAGE__->make_immutable;
}
##
##
# Imagine this is some code in a class...
#
use MyApp::Types qw( UserId Str );
# This will die because UserId is immutable now.
UserId->coercion->add_type_coercions(Str, sub { ... });
# This will work, and only affect this one attribute.
has user_id => (
is => 'ro',
isa => UserId->plus_coercions(Str, sub { ... }),
coerce => 1,
);