Type::Tiny is probably best known as a way of having Moose-like type constraints in Moo, but it can be used for so much more. This is the third in a series of posts showing other things you can use Type::Tiny for. This article along with part 1, part 2, and part 3 can be found on my blog and in the Cool Uses for Perl section of PerlMonks.

Even if you read the documentation of Types::Standard pretty thoroughly, you'd probably miss that you can do things like this:

use Types::Standard qw(is_ArrayRef is_HashRef) ; if ( is_ArrayRef ( $var )) { ... ; } elsif ( is_HashRef ( $var )) { ... ; }

It is documented that Types::Standard exports functions called ArrayRef and HashRef , which are constant-like functions returning Moose/Moo-compatible type constraint objects, but where did these is_ArrayRef and is_HashRef functions come from?

Well, their existence is documented in Type::Library, the type library base class used by Types::Standard. Any type library built with it will offer is_* variants of type constraints. These functions check their argument and return a boolean indicating whether it passes the type constraint.

The object-oriented way of writing these checks is like this:

use Types::Standard qw(ArrayRef HashRef) ; if ( ArrayRef -> check ( $var )) { ... ; } elsif ( HashRef -> check ( $var )) { ... ; }

Though the object-oriented way is a little slower because it will result in at least three sub calls (including a method call).

The is_* functions should be pretty darn fast, especially if Type::Tiny::XS is installed. Ref::Util::XS is faster, and Params::Util is sometimes faster, but using Type::Library-based type libraries (such as Types::Standard, Types::Common::Numeric, Types::Common::String, Types::Path::Tiny, Types::XSD, etc) will give you a richer selection of types that you can check.

Assertions

A common use for type checking functions is to do something like:

is_ArrayRef ( $var ) or die ( ... );

Type::Library-based type libraries offer a shortcut for this:

assert_ArrayRef ( $var );

The return value of the assert_* functions (if they don't die) is the parameter you passed to them, which makes it convenient to do things like:

use Types::Standard qw(assert_Object assert_ArrayRef) ; sub process_data { my $self = assert_Object ( $_ [ 0 ] ); my $data = assert_ArrayRef ( $_ [ 1 ] ); ... ; }

The object-oriented equivalent of assert_Object($thing) is Object->assert_return($thing) . Due to overloading Object->($thing) will also work.

Coercions

If a type constraint has coercions (like Path from Types::Path::Tiny), there's also a to_* function:

use Types::Path::Tiny qw( to_Path ) ; my $path = to_Path ( $thing );

Note that if a coercion fails, there is no exception thrown, and the original value is passed through unaltered. If you want to make sure coercion succeeded:

use Types::Path::Tiny qw( assert_Path to_Path ) ; my $path = assert_Path ( to_Path ( $thing ) );

The object-oriented equivalent of to_Path($thing) is Path->coerce($thing) . The object-oriented equivalent of assert_Path(to_Path($thing)) is Path->assert_coerce($thing) .

Parameterized Types

It would be pretty cool if you could do:

if ( is_ArrayRef [ Int ]( $var )) { ... ; }

But that wouldn't be syntactically valid Perl.

You can do this though:

use Types::Standard qw(ArrayRef Int) ; BEGIN { my $type = ArrayRef -> of ( Int ); *is_ArrayRef_of_Int = $type -> compiled_check ; *assert_ArrayRef_of_Int = \& { $type }; *to_ArrayRef_of_Int = sub { $type -> coerce ( @_ ) }; } if ( is_ArrayRef_of_Int ( $var )) { ... ; }

Exporting Tricks

To export just Object :

use Types::Standard qw(Object) ;

To export just is_Object :

use Types::Standard qw(is_Object) ;

To export Object and is_Object :

use Types::Standard qw(Object is_Object) ;

To export Object and all related functions ( is_Object , assert_Object , and to_Object ):

use Types::Standard qw(+Object) ;

To export Object , ArrayRef , and all the other types:

use Types::Standard qw(:types) ;

To export Object , ArrayRef , all the other types, and the related is_* functions:

use Types::Standard qw(:types :is) ;

To export Object , ArrayRef , all the other types, and the related is_* , assert_* , and to_* functions: