perlmoo

Run coercions inside a Type::Tiny custom constraint?


I have a custom DateTime type that has a coercion defined on it from string to DateTime, like so:

package Library;
use Type::Library -base, -declare => qw(DateTime);
use DateTime::Format::ISO8601;

class_type DateTime, { class => 'DateTime' };

coerce DateTime, from Str, via { DateTime::Format::ISO8601->parse_datetime($_) };

I'd like to use that DateTime type in a Dict, like so:

package MyObj;
use Moo;
$constraint = declare MyType, as Dict[ name => Str, date => DateTime ];

has 'whatsis' => ( is => 'ro', isa => $constraint );

And then call it as:

use MyObj;
my $obj = MyObj->new( whatsis => { name => 'Something', date => '2016-01-01' } );

I've tried adding coerce => 1 to the declaration of whatsis, but that did no good.

How do I create a custom type that inherits from Dict and runs the type coercions defined on the member types?


Solution

  • With lots of help from https://metacpan.org/pod/distribution/Type-Tiny/lib/Type/Tiny/Manual/Coercions.pod

    Library.pm:

    package Library;
    use Type::Library -base, -declare => qw(Datetime);
    use Type::Utils -all;
    use Types::Standard -all;
    use DateTime::Format::ISO8601;
    
    class_type Datetime, { class => 'DateTime' };
    coerce Datetime,
      from Str, via { DateTime::Format::ISO8601->parse_datetime($_) };
    
    declare 'MyType', as Dict[ name => Str, date => Datetime ], coercion => 1;
    

    MyObj.pm:

    package MyObj;
    use Moo;
    use Library -all;
    
    has 'whatsis' => ( is => 'ro', isa => MyType, coerce => 1 );
    

    tester.pl:

    #!perl
    use MyObj;
    my $obj = MyObj->new( whatsis => { name => 'Something', date => '2016-01-01' } );
    use Data::Dumper; print Dumper $obj;