1Type::Tiny::Manual::UsiUnsgeWritChoMnotor(i3b)uted PerlTDyopceu:m:eTnitnayt:i:oMnanual::UsingWithMoo(3)
2
3
4
6 Type::Tiny::Manual::UsingWithMoo - basic use of Type::Tiny with Moo
7
9 Type Constraints
10 Consider the following basic Moo class:
11
12 package Horse {
13 use Moo;
14 use namespace::autoclean;
15
16 has name => ( is => 'ro' );
17 has gender => ( is => 'ro' );
18 has age => ( is => 'rw' );
19 has children => ( is => 'ro', default => sub { [] } );
20 }
21
22 Code like this seems simple enough:
23
24 my $br = Horse->new(name => "Bold Ruler", gender => 'm', age => 16);
25 push @{ $br->children },
26 Horse->new(name => 'Secretariat', gender => 'm', age => 0);
27
28 However, once you step away from very simple use of the class, things
29 can start to go wrong. When we push a new horse onto "@{ $br->children
30 }", we are assuming that "$br->children" returned an arrayref.
31
32 What if the code that created the $br horse had instantiated it like
33 this?
34
35 my $br = Horse->new(name => "Bold Ruler", children => 'no');
36
37 It is for this reason that it's useful for the Horse class to perform
38 some basic sanity-checking on its own attributes.
39
40 package Horse {
41 use Moo;
42 use Types::Standard qw( Str Num ArrayRef );
43 use namespace::autoclean;
44
45 has name => ( is => 'ro', isa => Str );
46 has gender => ( is => 'ro', isa => Str );
47 has age => ( is => 'rw', isa => Num );
48 has children => (
49 is => 'ro',
50 isa => ArrayRef,
51 default => sub { return [] },
52 );
53 }
54
55 Now, if you instantiate a horse like this, it will throw an error:
56
57 my $br = Horse->new(name => "Bold Ruler", children => 'no');
58
59 The first type constraint we used here was Str. This is type constraint
60 that requires values to be strings.
61
62 Note that although "undef" is not a string, the empty string is still a
63 string and you will often want to check that a string is non-empty. We
64 could have done this:
65
66 use Types::Common::String qw( NonEmptyStr );
67 has name => ( is => 'ro', isa => NonEmptyStr );
68
69 While most of the type constraints we will use in this manual are
70 defined in Types::Standard, the Types::Common::String type library also
71 defines many useful type constraints.
72
73 We have required the horse's age to be a number. This is also a common,
74 useful type constraint. If we want to make sure it's a whole number, we
75 could use:
76
77 use Types::Standard qw( Int );
78 has age => ( is => 'rw', isa => Int );
79
80 Or because negative numbers make little sense as an age:
81
82 use Types::Common::Numeric qw( PositiveOrZeroInt );
83 has age => ( is => 'rw', isa => PositiveOrZeroInt );
84
85 The Types::Common::Numeric library defines many useful subtypes of Int
86 and Num, such as PositiveInt and PositiveOrZeroInt.
87
88 The last type constraint we've used in this example is ArrayRef. This
89 requires the value to be a reference to an array.
90
91 Types::Standard also provides HashRef and CodeRef type constraints. An
92 example of using the latter:
93
94 package Task {
95 use Moo;
96 use Types::Standard qw( CodeRef Bool );
97 has on_success => ( is => 'ro', isa => CodeRef );
98 has on_failure => ( is => 'ro', isa => CodeRef );
99 has finished => ( is => 'ro', isa => Bool, default => 0 );
100 ...;
101 }
102
103 my $task = Task->new(
104 on_success => sub { ... },
105 on_failure => sub { ... },
106 ...,
107 );
108
109 The Bool type constraint accepts "1" as a true value, and "0", "", or
110 undef as false values. No other values are accepted.
111
112 There exists an Object type constraint that accepts any blessed object.
113
114 package Horse {
115 use Moo;
116 use Types::Standard qw( Object );
117 use namespace::autoclean;
118
119 ...; # name, gender, age, children
120 has father => ( is => 'ro', isa => Object );
121 has mother => ( is => 'ro', isa => Object );
122 }
123
124 Finally, another useful type constraint to know about is Any:
125
126 use Types::Standard qw( Any );
127 has stuff => ( is => 'rw', isa => Any );
128
129 This type constraint allows any value; it is essentially the same as
130 not doing any type check, but makes your intent clearer. Where
131 possible, Type::Tiny will optimize away this type check, so it should
132 have little (if any) impact on performance.
133
134 Parameterized Types
135 Let's imagine we want to keep track of our horse's race wins:
136
137 package Horse {
138 use Moo;
139 use Types::Standard qw( Str Num ArrayRef );
140 use namespace::autoclean;
141
142 ...; # name, gender, age, children
143 has wins => (
144 is => 'ro',
145 isa => ArrayRef,
146 default => sub { return [] },
147 );
148 }
149
150 We can create a horse like this:
151
152 my $br = Horse->new(
153 name => "Bold Ruler",
154 gender => 'm',
155 age => 4,
156 wins => ["Futurity Stakes 1956", "Juvenile Stakes 1956"],
157 );
158
159 The list of wins is an arrayref of strings. The ArrayRef type
160 constraint prevents it from being set to a hashref, for example, but it
161 doesn't ensure that everything in the arrayref is a string. To do that,
162 we need to parameterize the type constraint:
163
164 has wins => (
165 is => 'ro',
166 isa => ArrayRef[Str],
167 default => sub { return [] },
168 );
169
170 Thanks to the ArrayRef[Str] parameterized type, the constructor will
171 throw an error if the arrayref you pass to it contains anything non-
172 string.
173
174 An alternative way of writing this is:
175
176 has wins => (
177 is => 'ro',
178 isa => ArrayRef->of(Str),
179 default => sub { return [] },
180 );
181
182 Which way you choose is largely a style preference. TIMTOWTDI!
183
184 Note that although the constructor and any setter/accessor method will
185 perform type checks, it is possible to bypass them using:
186
187 push @{ $br->wins }, $not_a_string;
188
189 The constructor isn't being called here, and although the accessor is
190 being called, it's being called as a reader, not a writer, so never
191 gets an opportunity to inspect the value being added. (It is possible
192 to use "tie" to solve this, but that will be covered later.)
193
194 And of course, if you directly poke at the underlying hashref of the
195 object, all bets are off:
196
197 $br->{wins} = $not_an_arrayref;
198
199 So type constraints do have limitations. Careful API design (and not
200 circumventing the proper API) can help.
201
202 The HashRef type constraint can also be parameterized:
203
204 package Design {
205 use Moo;
206 use Types::Standard qw( HashRef Str );
207 has colours => ( is => 'ro', isa => HashRef[Str] );
208 }
209
210 my $eiffel65 = Design->new(
211 colours => { house => "blue", little_window => "blue" },
212 );
213
214 The HashRef[Str] type constraint ensures the values of the hashref are
215 strings; it doesn't check the keys of the hashref because keys in Perl
216 hashes are always strings!
217
218 If you do need to constrain the keys, it is possible to use a
219 parameterized Map constraint:
220
221 use Types::Common::String qw( NonEmptyStr );
222 use Types::Standard qw( Map );
223 has colours => ( is => 'ro', isa => Map[NonEmptyStr, NonEmptyStr] );
224
225 Map takes two parameters; the first is a type to check keys against and
226 the second is a type to check values against.
227
228 Another useful type constraint is the Tuple type constraint.
229
230 use Types::Standard qw( ArrayRef Tuple );
231 use Types::Common::Numeric qw( PositiveInt );
232 use Types::Common::String qw( NonEmptyStr );
233
234 has wins => (
235 is => 'ro',
236 isa => ArrayRef[ Tuple[PositiveInt, NonEmptyStr] ],
237 default => sub { return [] },
238 );
239
240 The Tuple[PositiveInt, NonEmptyStr] type constraint checks that a value
241 is a two-element arrayref where the first element is a positive integer
242 and the second element is a non-empty string. For example:
243
244 my $br = Horse->new(
245 name => "Bold Ruler",
246 wins => [
247 [ 1956, "Futurity Stakes" ],
248 [ 1956, "Juvenile Stakes" ],
249 ],
250 );
251
252 As you can see, parameterized type constraints may be nested to
253 arbitrary depth, though of course the more detailed your checks become,
254 the slower they will perform.
255
256 It is possible to have tuples with variable length. For example, we may
257 wish to include the jockey name in our race wins when it is known.
258
259 use Types::Standard qw( ArrayRef Tuple Optional );
260 use Types::Common::Numeric qw( PositiveInt );
261 use Types::Common::String qw( NonEmptyStr );
262
263 has wins => (
264 is => 'ro',
265 isa => ArrayRef[
266 Tuple[ PositiveInt, NonEmptyStr, Optional[NonEmptyStr] ]
267 ],
268 default => sub { return [] },
269 );
270
271 The third element will be checked if it is present, but forgiven if it
272 is absent.
273
274 Or we could just allow tuples to contain an arbitrary list of strings
275 after the year and race name:
276
277 use Types::Standard qw( ArrayRef Tuple Str Slurpy );
278 use Types::Common::Numeric qw( PositiveInt );
279 use Types::Common::String qw( NonEmptyStr );
280
281 has wins => (
282 is => 'ro',
283 isa => ArrayRef[
284 Tuple[ PositiveInt, NonEmptyStr, Slurpy[ ArrayRef[Str] ] ]
285 ],
286 default => sub { return [] },
287 );
288
289 The Slurpy[ ArrayRef[Str] ] type will "slurp" all the remaining items
290 in the tuple into an arrayref and check it against ArrayRef[Str].
291
292 It's even possible to do this:
293
294 use Types::Standard qw( ArrayRef Tuple Any Slurpy );
295 use Types::Common::Numeric qw( PositiveInt );
296 use Types::Common::String qw( NonEmptyStr );
297
298 has wins => (
299 is => 'ro',
300 isa => ArrayRef[
301 Tuple[ PositiveInt, NonEmptyStr, Slurpy[Any] ]
302 ],
303 default => sub { return [] },
304 );
305
306 With this type constraint, any elements after the first two will be
307 slurped into an arrayref and we don't check that arrayref at all. (In
308 fact, the implementation of the Tuple type is smart enough to not
309 bother creating the temporary arrayref to check.)
310
311 Dict is the equivalent of Tuple for checking values of hashrefs.
312
313 use Types::Standard qw( ArrayRef Dict Optional );
314 use Types::Common::Numeric qw( PositiveInt );
315 use Types::Common::String qw( NonEmptyStr );
316
317 has wins => (
318 is => 'ro',
319 isa => ArrayRef[
320 Dict[
321 year => PositiveInt,
322 race => NonEmptyStr,
323 jockey => Optional[NonEmptyStr],
324 ],
325 ],
326 default => sub { return [] },
327 );
328
329 An example of using it:
330
331 my $br = Horse->new(
332 name => "Bold Ruler",
333 wins => [
334 { year => 1956, race => "Futurity Stakes", jockey => "Eddie" },
335 { year => 1956, race => "Juvenile Stakes" },
336 ],
337 );
338
339 The Slurpy type does work for Dict too:
340
341 Dict[
342 year => PositiveInt,
343 race => NonEmptyStr,
344 jockey => Optional[NonEmptyStr],
345 () => Slurpy[ HashRef[Str] ], # other Str values allowed
346 ]
347
348 And "Slurpy[Any]" means what you probably think it means:
349
350 Dict[
351 year => PositiveInt,
352 race => NonEmptyStr,
353 jockey => Optional[NonEmptyStr],
354 () => Slurpy[Any], # allow hashref to contain absolutely anything else
355 ]
356
357 Going back to our first example, there's an opportunity to refine our
358 ArrayRef constraint:
359
360 package Horse {
361 use Moo;
362 use Types::Standard qw( Str Num ArrayRef );
363 use namespace::autoclean;
364
365 has name => ( is => 'ro', isa => Str );
366 has gender => ( is => 'ro', isa => Str );
367 has age => ( is => 'rw', isa => Num );
368 has children => (
369 is => 'ro',
370 isa => ArrayRef[ InstanceOf["Horse"] ],
371 default => sub { return [] },
372 );
373 }
374
375 The InstanceOf["Horse"] type constraint checks that a value is a
376 blessed object in the Horse class. So the horse's children should be an
377 arrayref of other Horse objects.
378
379 Internally it just checks "$_->isa("Horse")" on each item in the
380 arrayref.
381
382 It is sometimes useful to instead check "$_->DOES($role)" or
383 "$_->can($method)" on an object. For example:
384
385 package MyAPI::Client {
386 use Moo;
387 use Types::Standard qw( HasMethods );
388
389 has ua => (is => 'ro', isa => HasMethods["get", "post"] );
390 }
391
392 The ConsumerOf and HasMethods parameterizable types allow you to easily
393 check roles and methods of objects.
394
395 The Enum parameterizable type allows you to accept a more limited set
396 of string values. For example:
397
398 use Types::Standard qw( Enum );
399 has gender => ( is => 'ro', isa => Enum["m","f"] );
400
401 Or if you want a little more flexibility, you can use StrMatch which
402 allows you to test strings against a regular expression:
403
404 use Types::Standard qw( StrMatch );
405 has gender => ( is => 'ro', isa => StrMatch[qr/^[MF]/i] );
406
407 Or StrLength to check the maximum and minimum length of a string:
408
409 use Types::Common::String qw( StrLength );
410 has name => ( is => 'ro', isa => StrLength[3, 100] );
411
412 The maximum can be omitted.
413
414 Similarly, the maximum and minimum values for a numeric type can be
415 expressed using IntRange and NumRange:
416
417 use Types::Common::Numeric qw( IntRange );
418 # values over 200 are probably an input error
419 has age => ( is => 'ro', isa => IntRange[0, 200] );
420
421 Parameterized type constraints are one of the most powerful features of
422 Type::Tiny, allowing a small set of constraints to be combined in
423 useful ways.
424
425 Type Coercions
426 It is often good practice to be liberal in what you accept.
427
428 package Horse {
429 use Moo;
430 use Types::Standard qw( Str Num ArrayRef Bool );
431 use namespace::autoclean;
432
433 ...; # name, gender, age, children, wins
434 has is_alive => ( is => 'rw', isa => Bool, coerce => 1 );
435 }
436
437 The "coerce" option indicates that if a value is given which does not
438 pass the Bool type constraint, then it should be coerced (converted)
439 into something that does.
440
441 The definition of Bool says that to convert a non-boolean to a bool,
442 you just do "!! $non_bool". So all of the following will be living
443 horses:
444
445 Horse->new(is_alive => 42)
446 Horse->new(is_alive => [])
447 Horse->new(is_alive => "false") # in Perl, string "false" is true!
448
449 Bool is the only type constraint in Types::Standard that has a coercion
450 defined for it. The NumericCode, UpperCaseStr, LowerCaseStr,
451 UpperCaseSimpleStr, and LowerCaseSimpleStr types from
452 Types::Common::String also have conversions defined.
453
454 The other built-in constraints do not define any coercions because it
455 would be hard to agree on what it means to coerce from, say, a HashRef
456 to an ArrayRef. Do we keep the keys? The values? Both?
457
458 But it is pretty simple to add your own coercions!
459
460 use Types::Standard qw( ArrayRef HashRef Str );
461 has things => (
462 is => 'rw',
463 isa => ArrayRef->plus_coercions(
464 HashRef, sub { [ values %$_ ] },
465 Str, sub { [ split /;/, $_ ] },
466 ),
467 coerce => 1,
468 );
469
470 (Don't ever forget the "coerce => 1"!)
471
472 If a hashref is provided, the values will be used, and if a string is
473 provided, it will be split on the semicolon. Of course, if an arrayref
474 if provided, it already passes the type constraint, so no conversion is
475 necessary.
476
477 The coercions should be pairs of "from types" and code to coerce the
478 value. The code can be a coderef (as above) or just string of Perl code
479 (as below). Strings of Perl code can usually be optimized better by
480 Type::Tiny's internals, so are generally preferred. Thanks to Perl's
481 "q{...}" operator, they can look just as clean and pretty as coderefs.
482
483 use Types::Standard qw( ArrayRef HashRef Str );
484 has things => (
485 is => 'rw',
486 isa => ArrayRef->plus_coercions(
487 HashRef, q{ [ values %$_ ] },
488 Str, q{ [ split /;/, $_ ] },
489 ),
490 coerce => 1,
491 );
492
493 Coercions are deeply applied automatically, so the following will do
494 what you expect.
495
496 has inputs => (
497 is => 'ro',
498 isa => ArrayRef->of(Bool),
499 coerce => 1
500 );
501
502 I am, of course, assuming you expect something like:
503
504 my $coerced = [ map { !!$_ } @$orig ];
505
506 If you were assuming that, congratulations! We are on the same
507 wavelength.
508
509 And of course you can still add more coercions to the inherited ones...
510
511 has inputs => (
512 is => 'ro',
513 isa => ArrayRef->of(Bool)->plus_coercions(Str, sub {...}),
514 coerce => 1
515 );
516
517 Type Defaults
518 A previous example included:
519
520 has children => (
521 is => 'ro',
522 isa => ArrayRef,
523 default => sub { return [] },
524 );
525
526 It's actually pretty common that you'll want an arrayref attribute to
527 default to being an empty arrayref, a numeric attribute to default to
528 zero, etc. Type::Tiny provides a method for that:
529
530 has children => (
531 is => 'ro',
532 isa => ArrayRef,
533 default => ArrayRef->type_default,
534 );
535
536 Many of the types in Types::Standard have sensible type defaults
537 defined.
538
539 Method Parameters
540 So far we have just concentrated on the definition of object
541 attributes, but type constraints are also useful to validate method
542 parameters.
543
544 Let's remember our attribute for keeping track of a horse's race wins:
545
546 use Types::Standard qw( ArrayRef Tuple Optional );
547 use Types::Common::Numeric qw( PositiveInt );
548 use Types::Common::String qw( NonEmptyStr );
549
550 has wins => (
551 is => 'ro',
552 isa => ArrayRef[
553 Tuple[ PositiveInt, NonEmptyStr, Optional[NonEmptyStr] ]
554 ],
555 default => sub { return [] },
556 );
557
558 Because we don't trust outside code to push new entries onto this
559 array, let's define a method in our class to do it.
560
561 package Horse {
562 ...;
563
564 sub add_win {
565 my $self = shift;
566 my ($year, $race, $jockey) = @_;
567 my $win = [
568 $year,
569 $race,
570 $jockey ? $jockey : (),
571 ];
572 push @{ $self->wins }, $win;
573 return $self;
574 }
575 }
576
577 This works pretty well, but we're still not actually checking the
578 values of $year, $race, and $jockey. Let's use Type::Params for that:
579
580 package Horse {
581 use Types::Common::Numeric qw( PositiveInt );
582 use Types::Common::String qw( NonEmptyStr );
583 use Type::Params qw( signature );
584 ...;
585
586 sub add_win {
587 state $check = signature(
588 method => 1, # allow for $self
589 positional => [
590 PositiveInt,
591 NonEmptyStr,
592 NonEmptyStr, { optional => 1 },
593 ],
594 );
595
596 my ( $self, $year, $race, $jockey ) = $check->(@_);
597 my $win = [
598 $year,
599 $race,
600 $jockey ? $jockey : (),
601 ];
602 push @{ $self->wins }, $win;
603 return $self;
604 }
605 }
606
607 The first time this method is called, it will compile a coderef called
608 $check. Then every time it is run, $check will be called to check the
609 method's parameters. It will throw an exception if they fail. $check
610 will also perform coercions if types have them (and you don't even need
611 to remember "coerce => 1"; it's automatic) and can even add in
612 defaults:
613
614 state $check = signature(
615 method => 1,
616 positional => [
617 PositiveInt,
618 NonEmptyStr,
619 NonEmptyStr, { default => sub { "Eddie" } },
620 ],
621 );
622
623 On older versions of Perl (prior to 5.10), "state" variables are not
624 available. A workaround is to replace this:
625
626 sub foo {
627 state $x = bar();
628 ...;
629 }
630
631 With this:
632
633 { # outer braces prevent other subs seeing $x
634 my $x; # declare $x before sub foo()
635 sub foo {
636 $x = bar();
637 ...;
638 }
639 }
640
641 (While we're having a general Perl syntax lesson, I'll note that
642 &$check with an ampersand and no parentheses is a shortcut for
643 "$check->(@_)" and actually runs slightly faster because it reuses the
644 @_ array for the called coderef. A lot of people dislike calling subs
645 with an ampersand, so we will stick to the "$check->(@_)" syntax in
646 these examples. But do consider using the shortcut!)
647
648 The generalized syntax for positional parameters in "signature" is:
649
650 state $check = signature(
651 %general_options,
652 positional => [
653 TypeForFirstParam, \%options_for_first_param,
654 TypeForSecondParam, \%options_for_second_param,
655 ...,
656 ],
657 );
658
659 As a shortcut for the "{ optional => 1 }" option, you can just use
660 Optional like in Tuple.
661
662 state $check = signature(
663 method => 1,
664 positional => [
665 PositiveInt,
666 NonEmptyStr,
667 Optional[NonEmptyStr],
668 ],
669 );
670
671 You can also use 0 and 1 as shortcuts for Optional[Any] and Any. The
672 following checks that the first parameter is a positive integer, the
673 second parameter is required (but doesn't care what value it is) and
674 the third parameter is allowed but not required.
675
676 state $check = signature positional => [ PositiveInt, 1, 0 ];
677
678 It is possible to accept a variable number of values using Slurpy:
679
680 package Horse {
681 use Types::Common::Numeric qw( PositiveInt );
682 use Types::Common::String qw( NonEmptyStr );
683 use Types::Standard qw( ArrayRef Slurpy );
684 use Type::Params qw( signature );
685 ...;
686
687 sub add_wins_for_year {
688 state $check = signature(
689 method => 1,
690 positional => [
691 PositiveInt,
692 Slurpy[ ArrayRef[NonEmptyStr] ],
693 ],
694 );
695
696 my ( $self, $year, $races ) = $check->(@_);
697 for my $race (@$races) {
698 push @{ $self->wins }, [$year, $race];
699 }
700 return $self;
701 }
702 }
703
704 It would be called like this:
705
706 $bold_ruler->add_wins_for_year(
707 1956,
708 "Futurity Stakes",
709 "Juvenile Stakes",
710 );
711
712 The additional parameters are slurped into an arrayref and checked
713 against ArrayRef[NonEmptyStr].
714
715 Optional parameters are only allowed after required parameters, and
716 Slurpy parameters are only allowed at the end. (And there can only be a
717 at most one Slurpy parameter!)
718
719 For methods that accept more than one or two parameters, it is often a
720 good idea to provide them as a hash. For example:
721
722 $horse->add_win(
723 year => 1956,
724 race => "Futurity Stakes",
725 jockey => "Eddie",
726 );
727
728 This can make your code more readable.
729
730 To accept named parameters, use the "named" option instead of
731 "positional".
732
733 package Horse {
734 use Types::Common::Numeric qw( PositiveInt );
735 use Types::Common::String qw( NonEmptyStr );
736 use Type::Params qw( signature );
737 ...;
738
739 sub add_win {
740 state $check = signature(
741 method => 1,
742 named => [
743 year => PositiveInt,
744 race => NonEmptyStr,
745 jockey => NonEmptyStr, { optional => 1 },
746 ],
747 );
748
749 my ( $self, $arg ) = $check->(@_);
750 my $win = [
751 $arg->year,
752 $arg->race,
753 $arg->has_jockey ? $arg->jockey : (),
754 ];
755 push @{ $self->wins }, $win;
756 return $self;
757 }
758 }
759
760 The "named" option will bundle all of your named arguments into an
761 object $arg. It allows your method to be called with a list of name-
762 value pairs or a hashref:
763
764 $horse->add_win(
765 year => 1956,
766 race => "Futurity Stakes",
767 jockey => "Eddie",
768 );
769
770 $horse->add_win( {
771 year => 1956,
772 race => "Juvenile Stakes",
773 } );
774
775 It is also possible for your check to accept named parameters but
776 return a positional list of parameters, using "named_to_list".
777
778 package Horse {
779 use Types::Common::Numeric qw( PositiveInt );
780 use Types::Common::String qw( NonEmptyStr );
781 use Type::Params qw( signature );
782 ...;
783
784 sub add_win {
785 state $check = signature(
786 method => 1,
787 named => [
788 year => PositiveInt,
789 race => NonEmptyStr,
790 jockey => NonEmptyStr, { optional => 1 },
791 ],
792 named_to_list => 1,
793 );
794
795 my ( $self, $year, $race, $jockey ) = $check->(@_);
796 my $win = [
797 $year,
798 $race,
799 $jockey ? $jockey : (),
800 ];
801 push @{ $self->wins }, $win;
802 return $self;
803 }
804 }
805
806 Optional and Slurpy named parameters are supported as you'd expect.
807
808 For more information on Type::Params, and third-party alternatives, see
809 Type::Tiny::Manual::Params.
810
812 Congratulations! I know this was probably a lot to take in, but you've
813 covered all of the essentials.
814
815 You can now set type constraints and coercions for attributes and
816 method parameters in Moo! You are familiar with a lot of the most
817 important and useful type constraints and understand parameterization
818 and how it can be used to build more specific type constraints.
819
820 (And I'll let you in on a secret. Using Type::Tiny with Moose or Mouse
821 instead of Moo is exactly the same. You can just replace "use Moo" with
822 "use Moose" in any of these examples and they should work fine!)
823
824 Here's your next step:
825
826 • Type::Tiny::Manual::UsingWithMoo2
827
828 Advanced use of Type::Tiny with Moo, including unions and
829 intersections, "stringifies_to", "numifies_to",
830 "with_attribute_values", and "where".
831
833 On very old versions of Moo "coerce => 1" is not supported. Instead you
834 will need to provide a coderef or object overloading "&{}" to coerce.
835 Type::Tiny can provide you with an overloaded object.
836
837 package Horse {
838 use Moo;
839 use Types::Standard qw( Str Num ArrayRef Bool );
840 use namespace::autoclean;
841
842 ...; # name, gender, age, children, wins
843 has is_alive => (
844 is => 'rw',
845 isa => Bool,
846 coerce => Bool->coercion, # overloaded object
847 );
848 }
849
850 If you have a very old version of Moo, please upgrade to at least Moo
851 1.006000 which was the version that added support for "coerce => 1".
852
854 Toby Inkster <tobyink@cpan.org>.
855
857 This software is copyright (c) 2013-2014, 2017-2023 by Toby Inkster.
858
859 This is free software; you can redistribute it and/or modify it under
860 the same terms as the Perl 5 programming language system itself.
861
863 THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
864 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
865 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
866
867
868
869perl v5.36.0 2023-01-04Type::Tiny::Manual::UsingWithMoo(3)