The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Type::Tiny::Manual::Libraries - how to build a type library with Type::Tiny, Type::Library and Type::Utils

SYNOPSIS

A type library is a collection of type constraints, optionally with coercions.

The following is an example type library:

   package MyTypes::DateTime;
   
   use Type::Library
      -base,
      -declare => qw( Datetime DatetimeHash EpochHash );
   use Type::Utils;
   use Type::Standard -types;
   
   class_type Datetime, { class => "DateTime" };
   
   declare DatetimeHash,
      as Dict[
         year       => Int,
         month      => Optional[ Int ],
         day        => Optional[ Int ],
         hour       => Optional[ Int ],
         minute     => Optional[ Int ],
         second     => Optional[ Int ],
         nanosecond => Optional[ Int ],
         time_zone  => Optional[ Str ],
      ];
   
   declare EpochHash,
      as Dict[ epoch => Int ];
   
   coerce Datetime,
      from Int,          via { "DateTime"->from_epoch(epoch => $_) },
      from Undef,        via { "DateTime"->now },
      from DatetimeHash, via { "DateTime"->new(%$_) };
      from EpochHash,    via { "DateTime"->from_epoch(%$_) };
   
   1;

DESCRIPTION

Here's a line by line description of what's going on in the type library.

   package MyTypes::DateTime;

Type libraries are packages.

   use Type::Library
      -base,
      -declare => qw( Datetime DatetimeHash EpochHash );

The -base part is used to establish inheritance. It makes MyTypes::DateTime a child class of Type::Library.

Declaring the types we're going to define ahead of their definition allows us to use them as barewords later on. (Note that in code which uses our type library, the types will always be available as barewords. The declaration above just allows us to use them within the library itself.)

   use Type::Utils;

Imports some utility functions from Type::Utils. These will be useful for defining our types and the relationships between them.

   use Type::Standard -types;

Here we import a standard set of type constraints from Type::Standard. There is no need to do this, but it's often helpful to have a base set of types which we can define our own in terms of.

Note that although we've imported the types to be able to use in our library, we haven't added the types to our library. We've imported Str, but other people won't be able to re-import Str from our library. If you actually want your library to extend another library, do this instead:

   BEGIN { extends "Some::Other::Library" };

OK, now we're ready to declare a few types.

   class_type Datetime, { class => "DateTime" };

This creates a type constraint named "Datetime" which is all objects blessed into the DateTime package. Because this type constraint is not anonymous (it has a name), it will be automagically installed into the type library.

The next two statements declare two further types constraints, using type constraints from the Type::Standard library. Let's look at EpochHash in more detail. This is a hashref with one key called "epoch" and a value which is an integer.

   declare EpochHash,
      as Dict[ epoch => Int ];

EpochHash inherits from the Dict type defined in Type::Standard. It equally could have been defined as:

   declare EpochHash,
      as HashRef[Int],
      where { scalar(keys(%$_))==1 and exists $_->{epoch} };

Or even:

   declare EpochHash,
      where {
             ref($_) eq "HASH"
         and scalar(keys(%$_))==1
         and exists $_->{epoch}
      };

Lastly we set up coercions. It's best to define all your types before you define any coercions.

   coerce Datetime,
      from Int,          via { "DateTime"->from_epoch(epoch => $_) },
      from Undef,        via { "DateTime"->now },
      from DatetimeHash, via { "DateTime"->new(%$_) },
      from EpochHash,    via { "DateTime"->from_epoch(%$_) };

These are simply coderefs that will be fired when you want a Datetime, but are given something else.

ADVANCED TOPICS

Messages

Inlining

Parameterized Constraints