{
    "mode": "perldoc",
    "parameter": "Type::Tiny::Manual::UsingWithMoo2",
    "section": "",
    "url": "https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny%3A%3AManual%3A%3AUsingWithMoo2/json",
    "generated": "2026-06-12T05:51:32Z",
    "sections": {
        "NAME": {
            "content": "Type::Tiny::Manual::UsingWithMoo2 - advanced use of Type::Tiny with Moo\n",
            "subsections": []
        },
        "MANUAL": {
            "content": "What is a Type?\nSo far all the examples have shown you how to work with types, but we haven't looked at what a\ntype actually *is*.\n\nuse Types::Standard qw( Int );\nmy $type = Int;\n\n\"Int\" in the above code is just a function called with zero arguments which returns a blessed\nPerl object. It is this object that defines what the Int type is and is responsible for checking\nvalues meet its definition.\n\nuse Types::Standard qw( HashRef Int );\nmy $type = HashRef[Int];\n\nThe \"HashRef\" function, if called with no parameters returns the object defining the HashRef\ntype, just like the \"Int\" function did before. But the difference here is that it's called with\na parameter, an arrayref containing the Int type object. It uses this to make the HashRef[Int]\ntype and returns that.\n\nLike any object, you can call methods on it. The most important methods to know about are:\n\n# check the value and return a boolean\n#\n$type->check($value);\n\n# return an error message about $value failing the type check\n# but don't actually check the value\n#\n$type->getmessage($value);\n\n# coerce the value\n#\nmy $coerced = $type->coerce($value);\n\nWe've already seen some other methods earlier in the tutorial.\n\n# create a new type, same as the old type, but that has coercions\n#\nmy $newtype = $type->pluscoercions( ... );\n\n# different syntax for parameterized types\n#\nmy $href = HashRef;\nmy $int = Int;\nmy $hrefofint = $href->of($int);\n\nSo now you should understand this:\n\nuse Types::Standard qw( ArrayRef Dict Optional );\nuse Types::Common::Numeric qw( PositiveInt );\nuse Types::Common::String qw( NonEmptyStr );\n\nmy $RaceInfo = Dict[\nyear    => PositiveInt,\nrace    => NonEmptyStr,\njockey  => Optional[NonEmptyStr],\n];\n\nhas latestevent  => ( is => 'rw', isa => $RaceInfo );\nhas wins          => ( is => 'rw', isa => ArrayRef[$RaceInfo] );\nhas losses        => ( is => 'rw', isa => ArrayRef[$RaceInfo] );\n\nThis can help you avoid repetition if you have a complex parameterized type that you need to\nreuse a few times.\n\n\"where\"\nOne of the most useful methods you can call on a type object is \"where\".\n\nuse Types::Standard qw( Int );\n\nhas luckynumber => (\nis   => 'ro',\nisa  => Int->where(sub { $ != 13 }),\n);\n\nI think you already understand what it does. It creates a new type constraint on the fly,\nrestricting the original type.\n\nLike with coercions, these restrictions can be expressed as a coderef or as a string of Perl\ncode, operating on the $ variable. And like with coercions, using a string of code will result\nin better performance.\n\nuse Types::Standard qw( Int );\n\nhas luckynumber => (\nis   => 'ro',\nisa  => Int->where(q{ $ != 13 }),\n);\n\nLet's coerce a hashref of strings from an even-sized arrayref of strings:\n\nuse Types::Standard qw( HashRef ArrayRef Str );\n\nhas stringhash => (\nis   => 'ro',\nisa  => HashRef->of(Str)->pluscoercions(\nArrayRef->of(Str)->where(q{ @$ % 2 == 0 }), q{\nmy %h = @$;\n\\%h;\n},\n),\ncoerce => 1,  # never forget!\n);\n\nIf you understand that, you really are in the advanced class. Congratulations!\n",
            "subsections": [
                {
                    "name": "Unions",
                    "content": "Sometimes you want to accept one thing or another thing. This is pretty easy with Type::Tiny.\n\nuse Types::Standard qw( HashRef ArrayRef Str );\n\nhas strings => (\nis    => 'ro',\nisa   => ArrayRef[Str] | HashRef[Str],\n);\n\nType::Tiny overloads the bitwise or operator so stuff like this should \"just work\".\n\nThat said, now any code that calls \"$self->strings\" will probably need to check if the value is\nan arrayref or a hashref before doing anything with it. So it may be simpler overall if you just\nchoose one of the options and coerce the other one into it.\n"
                },
                {
                    "name": "Intersections",
                    "content": "Similar to a union is an intersection.\n\npackage MyAPI::Client {\nuse Moo;\nuse Types::Standard qw( HasMethods InstanceOf );\n\nhas ua => (\nis    => 'ro',\nisa   => (InstanceOf[\"MyUA\"]) & (HasMethods[\"storecookie\"]),\n);\n}\n\nHere we are checking that the UA is an instance of the MyUA class and also offers the\n\"storecookie\" method. Perhaps \"storecookie\" isn't provided by the MyUA class itself, but\nseveral subclasses of MyUA provide it.\n\nIntersections are not useful as often as unions are. This is because they often make no sense.\n\"(ArrayRef) & (HashRef)\" would be a reference which was simultaneously pointing to an array and\na hash, which is impossible.\n\nNote that when using intersections, it is good practice to put parentheses around each type.\nThis is to disambiguate the meaning of \"&\" for Perl, because Perl uses it as the bitwise and\noperator but also as the sigil for subs.\n"
                },
                {
                    "name": "Complements",
                    "content": "For any type Foo there is a complementary type ~Foo (pronounced \"not Foo\").\n\npackage My::Class {\nuse Moo;\nuse Types::Standard qw( ArrayRef CodeRef );\n\nhas things => ( is => 'ro', isa => ArrayRef[~CodeRef] );\n}\n\n\"things\" is now an arrayref of anything except coderefs.\n\nIf you need a number that is *not* an integer:\n\nNum & ~Int\n\nTypes::Standard includes two types which are complements of each other: Undef and Defined.\n\nNegativeInt might seem to be the complement of PositiveOrZeroInt but when you think about it, it\nis not. There are values that fall into neither category, such as non-integers, non-numeric\nstrings, references, undef, etc.\n\n\"stringifiesto\" and \"numifiesto\"\nThe Object type constraint provides \"stringifiesto\" and \"numifiesto\" methods which are\nprobably best explained by examples.\n\n\"Object->numifiesto(Int)\" means any object where \"0 + $object\" is an integer.\n\n\"Object->stringifiesto(StrMatch[$re])\" means any object where \"$object\" matches the regular\nexpression.\n\n\"Object->stringifiesto($re)\" also works as a shortcut.\n\n\"Object->numifiesto($coderef)\" and \"Object->stringifiesto($coderef)\" also work, where the\ncoderef checks $ and returns a boolean.\n\nOther types which are also logically objects, such as parameterized HasMethods, InstanceOf, and\nConsumerOf should also provide \"stringifiesto\" and \"numifiesto\" methods.\n\n\"stringifiesto\" and \"numifiesto\" work on unions if *all* of the type constraints in the union\noffer the method.\n\n\"stringifiesto\" and \"numifiesto\" work on intersections if *at least one of* of the type\nconstraints in the intersection offers the method.\n\n\"withattributevalues\"\nAnother one that is probably best explained using an example:\n\npackage Horse {\nuse Types::Standard qw( Enum Object );\n\nhas gender  => (\nis  => 'ro',\nisa => Enum['m', 'f'],\n);\nhas father  => (\nis  => 'ro',\nisa => Object->withattributevalues(gender => Enum['m']),\n);\nhas mother  => (\nis  => 'ro',\nisa => Object->withattributevalues(gender => Enum['f']),\n);\n}\n\nIn this example when you set a horse's father, it will call \"$father->gender\" and check that it\nmatches Enum['m'].\n\nThis method is in the same family as \"stringifiesas\" and \"numifiesas\", so like those, it only\napplies to Object and similar type constraints, can work on unions/intersections under the same\ncircumstances, and will also accept coderefs and regexps.\n\nhas father  => (\nis  => 'ro',\nisa => Object->withattributevalues(gender => sub { $ eq 'm' }),\n);\nhas mother  => (\nis  => 'ro',\nisa => Object->withattributevalues(gender => qr/^f/i),\n);\n\nAll of \"stringifiesas\", \"numifiesas\", and \"withattributesas\" are really just wrappers around\n\"where\". The following two are roughly equivalent:\n\nmy $type1 = Object->withattributevalues(foo => Int, bar => Num);\n\nmy $type2 = Object->where(sub {\nInt->check( $->foo ) and Num->check( $->bar )\n});\n\nThe first will result in better performing code though.\n"
                },
                {
                    "name": "Tied Variables",
                    "content": "It is possible to tie variables to a type constraint.\n\nuse Types::Standard qw(Int);\n\ntie my $n, Int, 4;\n\nprint \"$n\\n\";   # says \"4\"\n$n = 5;         # ok\n$n = \"foo\";     # dies\n\nThis feature requires Type::Tie which is a separate thing to install. Type::Tiny will\nautomatically load Type::Tie in the background if it detects you're trying to tie a variable to\na type.\n\nYou can also tie arrays:\n\ntie my @numbers, Int;\npush @numbers, 1 .. 10;\n\nAnd hashes:\n\ntie my %numbers, Int;\n$numbers{lucky}   = 7;\n$numbers{unlucky} = 13;\n\nEarlier in the manual, it was mentioned that there is a problem with code like this:\n\npush @{ $horse->children }, $nonhorse;\n\nThis can be solved using tied variables.\n\ntie @{ $horse->children }, InstanceOf[\"Horse\"];\n\nHere is a longer example using builders and triggers.\n\npackage Horse {\nuse Moo;\nuse Types::Standard qw( Str Num ArrayRef InstanceOf );\nuse Type::Params qw(compile);\nuse namespace::autoclean;\n\nmy $ThisClass = InstanceOf[ PACKAGE ];\n\nhas name       => ( is => 'ro',    isa => Str );\nhas gender     => ( is => 'ro',    isa => Str );\nhas age        => ( is => 'rw',    isa => Num );\nhas children   => (\nis        => 'rw',\nisa       => ArrayRef[$ThisClass],\nbuilder   => \"buildchildren\",\ntrigger   => sub { shift->triggerchildren(@) },\n);\n\n# tie a default arrayref\nsub buildchildren {\nmy $self = shift;\ntie my @kids, $ThisClass;\n\\@kids;\n}\n\n# this method will tie an arrayref provided by the caller\nsub triggerchildren {\nmy $self = shift;\nmy ($new) = @;\ntie @$new, $ThisClass;\n}\n\nsub addchild {\nstate $check = compile($ThisClass, $ThisClass);\nmy ($self, $kid) = &$check;\npush @{ $self->children }, $kid;\nreturn $self;\n}\n}\n\nNow it's pretty much impossible for the caller to make a mess by adding a non-horse as a child.\n"
                }
            ]
        },
        "NEXT STEPS": {
            "content": "Here's your next step:\n\n*   Type::Tiny::Manual::UsingWithMoo3\n\nThere's more than one way to do it! Alternative ways of using Type::Tiny, including type\nregistries, exported functions, and \"dwimtype\".\n",
            "subsections": []
        },
        "AUTHOR": {
            "content": "Toby Inkster <tobyink@cpan.org>.\n",
            "subsections": []
        },
        "COPYRIGHT AND LICENCE": {
            "content": "This software is copyright (c) 2013-2014, 2017-2021 by Toby Inkster.\n\nThis is free software; you can redistribute it and/or modify it under the same terms as the Perl\n5 programming language system itself.\n",
            "subsections": []
        },
        "DISCLAIMER OF WARRANTIES": {
            "content": "THIS PACKAGE IS PROVIDED \"AS IS\" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\nWITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.\n",
            "subsections": []
        }
    },
    "summary": "Type::Tiny::Manual::UsingWithMoo2 - advanced use of Type::Tiny with Moo",
    "flags": [],
    "examples": [],
    "see_also": []
}