# Type::Tiny::Manual::UsingWithMoo3 - alternative use of Type::Tiny with Moo - perldoc - [phpMan]

## NAME
    [Type::Tiny::Manual::UsingWithMoo3](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny%3A%3AManual%3A%3AUsingWithMoo3/markdown) - alternative use of [Type::Tiny](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny/markdown) with Moo

## MANUAL
### Type Registries
    In all the examples so far, we have imported a collection of type constraints into each class:

      package Horse {
        use Moo;
        use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) qw( Str ArrayRef HashRef Int Any InstanceOf );
        use [Types::Common::Numeric](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon%3A%3ANumeric/markdown) qw( PositiveInt );
        use [Types::Common::String](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon%3A%3AString/markdown) qw( NonEmptyStr );

        has name    => ( is => 'ro', isa => Str );
        has father  => ( is => 'ro', isa => InstanceOf["Horse"] );
        ...;
      }

    This creates a bunch of subs in the Horse namespace, one for each type. We've used
    [namespace::autoclean](https://www.chedong.com/phpMan.php/perldoc/namespace%3A%3Aautoclean/markdown) to clean these up later.

    But it is also possible to avoid pulling all these into the Horse namespace. Instead we'll use a
    type registry:

      package Horse {
        use Moo;
        use [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown) qw( t );

        t->add_types('-Standard');
        t->add_types('-[Common::String](https://www.chedong.com/phpMan.php/perldoc/Common%3A%3AString/markdown)');
        t->add_types('-[Common::Numeric](https://www.chedong.com/phpMan.php/perldoc/Common%3A%3ANumeric/markdown)');

        t->alias_type('InstanceOf["Horse"]' => 'Horsey');

        has name     => ( is => 'ro', isa => t('Str') );
        has father   => ( is => 'ro', isa => t('Horsey') );
        has mother   => ( is => 'ro', isa => t('Horsey') );
        has children => ( is => 'ro', isa => t('ArrayRef[Horsey]') );
        ...;
      }

    You don't even need to import the t() function. [Types::Registry](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ARegistry/markdown) can be used in an entirely
    object-oriented way.

      package Horse {
        use Moo;
        use [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown);

        my $reg = [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown)->for_me;

        $reg->add_types('-Standard');
        $reg->add_types('-[Common::String](https://www.chedong.com/phpMan.php/perldoc/Common%3A%3AString/markdown)');
        $reg->add_types('-[Common::Numeric](https://www.chedong.com/phpMan.php/perldoc/Common%3A%3ANumeric/markdown)');

        $reg->alias_type('InstanceOf["Horse"]' => 'Horsey');

        has name => ( is => 'ro', isa => $reg->lookup('Str') );
        ...;
      }

    You could create two registries with entirely different definitions for the same named type.

      my $dracula = Aristocrat->new(name => 'Dracula');

      package AristocracyTracker {
        use [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown);

        my $reg1 = [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown)->new;
        $reg1->add_types('-[Common::Numeric](https://www.chedong.com/phpMan.php/perldoc/Common%3A%3ANumeric/markdown)');
        $reg1->alias_type('PositiveInt' => 'Count');

        my $reg2 = [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown)->new;
        $reg2->add_types('-Standard');
        $reg2->alias_type('InstanceOf["Aristocrat"]' => 'Count');

        $reg1->lookup("Count")->assert_valid("1");
        $reg2->lookup("Count")->assert_valid($dracula);
      }

    [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown) uses "AUTOLOAD", so things like this work:

      $reg->ArrayRef->of( $reg->Int );

    Although you can create as many registries as you like, [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown) will create a default
    registry for each package.

      # Create a new empty registry.
      #
      my $reg = [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown)->new;

      # Get the default registry for my package.
      # It will be pre-populated with any types we imported using `use`.
      #
      my $reg = [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown)->for_me;

      # Get the default registry for some other package.
      #
      my $reg = [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown)->for_class("Horse");

    Type registries are a convenient place to store a bunch of types without polluting your
    namespace. They are not the same as type libraries though. [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown),
    [Types::Common::String](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon%3A%3AString/markdown), and [Types::Common::Numeric](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon%3A%3ANumeric/markdown) are type libraries; packages that export types
    for others to use. We will look at how to make one of those later.

    For now, here's the best way to think of the difference:

    *   Type registry

        Curate a collection of types for me to use here in this class. This collection is an
        implementation detail.

    *   Type library

        Export a collection of types to be used across multiple classes. This collection is part of
        your API.

### Importing Functions
    We've seen how, for instance, [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) exports a sub called "Int" that returns the Int
    type object.

      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) qw( Int );

      my $type = Int;
      $type->check($value) or die $type->get_message($value);

    Type libraries are also capable of exporting other convenience functions.

   "is_*"
    This is a shortcut for checking a value meets a type constraint:

      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) qw( is_Int );

      if ( is_Int $value ) {
        ...;
      }

    Calling is_Int($value) will often be marginally faster than calling "Int->check($value)" because
    it avoids a method call. (Method calls in Perl end up slower than normal function calls.)

    Using things like "is_ArrayRef" in your code might be preferable to "ref($value) eq "ARRAY""
    because it's neater, leads to more consistent type checking, and might even be faster.
    ([Type::Tiny](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny/markdown) can be pretty fast; it is sometimes able to export these functions as XS subs.)

    If checking type constraints like "is_ArrayRef" or "is_InstanceOf", there's no way to give a
    parameter. "is_ArrayRef[Int]($value)" doesn't work, and neither does "is_ArrayRef(Int, $value)"
    nor "is_ArrayRef($value, Int)". For some types like "is_InstanceOf", this makes them fairly
    useless; without being able to give a class name, it just acts the same as "is_Object". See
    "Exporting Parameterized Types" for a solution. Also, check out isa.

    There also exists a generic "is" function.

      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) qw( ArrayRef Int );
      use [Type::Utils](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3AUtils/markdown) qw( is );

      if ( is ArrayRef[Int], \@numbers ) {
        ...;
      }

   "assert_*"
    While is_Int($value) returns a boolean, assert_Int($value) will throw an error if the value does
    not meet the constraint, and return the value otherwise. So you can do:

      my $sum = assert_Int($x) + assert_Int($y);

    And you will get the sum of integers $x and $y, and an explosion if either of them is not an
    integer!

    Assert is useful for quick parameter checks if you are avoiding [Type::Params](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3AParams/markdown) for some strange
    reason:

      sub add_numbers {
        my $x = assert_Num(shift);
        my $y = assert_Num(shift);
        return $x + $y;
      }

    You can also use a generic "assert" function.

      use [Type::Utils](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3AUtils/markdown) qw( assert );

      sub add_numbers {
        my $x = assert Num, shift;
        my $y = assert Num, shift;
        return $x + $y;
      }

   "to_*"
    This is a shortcut for coercion:

      my $truthy = to_Bool($value);

    It trusts that the coercion has worked okay. You can combine it with an assertion if you want to
    make sure.

      my $truthy = assert_Bool(to_Bool($value));

   Shortcuts for exporting functions
    This is a little verbose:

      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) qw( Bool is_Bool assert_Bool to_Bool );

    Isn't this a little bit nicer?

      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) qw( +Bool );

    The plus sign tells a type library to export not only the type itself, but all of the
    convenience functions too.

    You can also use:

      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) -types;   # export Int, Bool, etc
      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) -is;      # export is_Int, is_Bool, etc
      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) -assert;  # export assert_Int, assert_Bool, etc
      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) -to;      # export to_Bool, etc
      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) -all;     # just export everything!!!

    So if you imagine the functions exported by [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) are like this:

      qw(
        Str             is_Str          assert_Str
        Num             is_Num          assert_Num
        Int             is_Int          assert_Int
        Bool            is_Bool         assert_Bool     to_Bool
        ArrayRef        is_ArrayRef     assert_ArrayRef
      );
      # ... and more

    Then "+" exports a horizonal group of those, and "-" exports a vertical group.

### Exporting Parameterized Types
    It's possible to export parameterizable types like ArrayRef, but it is also possible to export
    *parameterized* types.

      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) qw( ArrayRef Int );
      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) (
        '+ArrayRef' => { of => Int, -as => 'IntList' },
      );

      has numbers => (is => 'ro', isa => IntList);

    Using is_IntList($value) should be significantly faster than "ArrayRef->of(Int)->check($value)".

    This trick only works for parameterized types that have a single parameter, like ArrayRef,
    HashRef, InstanceOf, etc. (Sorry, "Dict" and "Tuple"!)

### Lexical imports
    [Type::Tiny](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny/markdown) 2.0 combined with Perl 5.37.2+ allows lexically scoped imports. So:

      my $is_ok = do {
        use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) -lexical, qw( Str ArrayRef );
        ArrayRef->of( Str )->check( \@things );
      };

      # The Str and ArrayRef types aren't defined here.

  Do What I Mean!
      use [Type::Utils](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3AUtils/markdown) qw( dwim_type );

      dwim_type("ArrayRef[Int]")

    "dwim_type" will look up a type constraint from a string and attempt to guess what you meant.

    If it's a type constraint that you seem to have imported with "use", then it should find it.
    Otherwise, if you're using Moose or Mouse, it'll try asking those. Or if it's in
    [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown), it'll look there. And if it still has no idea, then it will assume
### dwim_type

    It just does a big old bunch of guessing.

    The "is" function will use "dwim_type" if you pass it a string as a type.

      use [Type::Utils](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3AUtils/markdown) qw( is );

      if ( is "ArrayRef[Int]", \@numbers ) {
        ...;
      }

### [Types::Common](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon/markdown)
    Notice that in a lot of examples we're importing one or two functions each from a few different
    modules:

      use [Types::Common::Numeric](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon%3A%3ANumeric/markdown) qw( PositiveInt );
      use [Types::Common::String](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon%3A%3AString/markdown) qw( NonEmptyStr );
      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) qw( ArrayRef Slurpy );
      use [Type::Params](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3AParams/markdown) qw( signature );

    A module called [Types::Common](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon/markdown) exists which acts as a single place you can use for importing most
    of [Type::Tiny](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny/markdown)'s commonly used types and functions.

      use [Types::Common](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon/markdown) qw(
        PositiveInt NonEmptyStr ArrayRef Slurpy
        signature
      );

    [Types::Common](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon/markdown) provides:

    *   All the types from [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown).

    *   All the types from [Types::Common::Numeric](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon%3A%3ANumeric/markdown) and [Types::Common::String](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon%3A%3AString/markdown).

    *   All the types from [Types::TypeTiny](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ATypeTiny/markdown).

    *   The "-sigs" tag from [Type::Params](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3AParams/markdown).

    *   The t() function from [Type::Registry](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ARegistry/markdown).

## NEXT STEPS
    You now know pretty much everything there is to know about how to use type libraries.

    Here's your next step:

    *   [Type::Tiny::Manual::Libraries](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny%3A%3AManual%3A%3ALibraries/markdown)

        Defining your own type libraries, including extending existing libraries, defining new
        types, adding coercions, defining parameterizable types, and the declarative style.

## AUTHOR
    Toby Inkster <<tobyink@cpan.org>>.

## COPYRIGHT AND LICENCE
    This software is copyright (c) 2013-2014, 2017-2023 by Toby Inkster.

    This is free software; you can redistribute it and/or modify it under the same terms as the Perl
    5 programming language system itself.

## DISCLAIMER OF WARRANTIES
    THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
    WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
    PURPOSE.

