I have the following Type defined.

package Types; use v5.34; use warnings; use Type::Utils qw( as coerce declare from via ); use Types::Common qw( Enum Str ); use Type::Library -base, -declare => qw( CreditType InvoiceType ); declare InvoiceType, as Enum [qw/ ACCPAY ACCREC /]; coerce InvoiceType, from Str, via { #warn "Trying to coerce $_\n"; my %types = ( Invoice => 'ACCREC', SupplierInvoice => 'ACCPAY', ); #my $ret = $types{$_}; #warn "Returning $ret\n"; return $types{$_}; } ; declare CreditType, as Enum [qw/ ACCPAYCREDIT ACCRECCREDIT /]; coerce CreditType, from Str, via { warn "Trying to coerce $_\n"; my %types = ( Credit => 'ACCRECCREDIT', SupplierCredit => 'ACCPAYCREDIT', ); my $ret = $types{$_}; warn "Returning $ret\n"; return $types{$_}; } ; 1;

I have a class that uses the types as a union, this or that

package MyApp; use v5.34; use warnings; use Moo; use Types qw/ InvoiceType CreditType /; has 'type' => ( is => 'ro', isa => InvoiceType | CreditType, required => 1, coerce => 1, ); sub run { my ($self) = @_; say "Running with ".$self->type; } 1;

I have a test to make sure it's doing what I expect `t/type.t`

#!/opt/perl5/bin/perl use v5.34; use warnings; use Test::More; use Types qw( InvoiceType CreditType ); { subtest 'Type coercion' => sub { is InvoiceType->coerce('Invoice'), 'ACCREC', 'Can coerce a sales invoice'; is InvoiceType->coerce('SupplierInvoice'), 'ACCPAY', 'Can coerce a supplier invoice'; is CreditType->coerce('Credit'), 'ACCRECCREDIT', 'Can coerce a credit type'; is CreditType->coerce('SupplierCredit'), 'ACCPAYCREDIT', 'Can coerce a supplier credit type'; }; } { my $class = 'MyApp'; use_ok($class); subtest 'Class coercion' => sub { for my $t ( qw/Invoice SupplierInvoice Credit SupplierCredit / + ) { note "Type=$t"; my $x = new_ok($class => [ type => $t ]); note "Now Type=".$x->type; } }; } done_testing;
t/type.t .. # Subtest: Type coercion ok 1 - Can coerce a sales invoice ok 2 - Can coerce a supplier invoice ok 3 - Can coerce a credit type ok 4 - Can coerce a supplier credit type 1..4 ok 1 - Type coercion ok 2 - use MyApp; # Subtest: Class coercion # Type=Invoice ok 1 - An object of class 'MyApp' isa 'MyApp' # Type=SupplierInvoice ok 2 - An object of class 'MyApp' isa 'MyApp' # Type=Credit not ok 3 - MyApp->new() died # Failed test 'MyApp->new() died' # at t/type.t line 31. # Error was: Undef did not pass type constraint "InvoiceType| +CreditType" (in $args->{"type"}) at /home/dpaikkos/spl/local/lib/perl +5/Test/More.pm line 741 # "InvoiceType|CreditType" requires that the value pass "Credi +tType" or "InvoiceType" # Undef did not pass type constraint "InvoiceType" # "InvoiceType" is a subtype of "Enum["ACCPAY","ACCREC"]" # "Enum["ACCPAY","ACCREC"]" requires that the value is def +ined # Undef did not pass type constraint "CreditType"

I excel at leaving typos in my code but I am pretty sure there are none in the code so far. The coercions appear to work in a stand alone fashion but when used as a union, the 2nd Type does not appear to apply the coercion. If I swap the "CreditType" to be the first item, I find that the InvoiceType fails.

I suspect I could use some kind of named parameterized coercion and `plus_coercions` but I hit this snag and haven't been able to move forward.

Does anyone have any insights into what I'm doing wrong?

Thanks in advance

In reply to Type coercion and union by tomred

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.