1Type::Tiny::Manual::LibUrsaerrieCso(n3t)ributed Perl DocTuympeen:t:aTtiinoyn::Manual::Libraries(3)
2
3
4

NAME

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

SYNOPSIS

10       A type library is a collection of type constraints, optionally with
11       coercions.
12
13       The following is an example type library:
14
15          package Example::Types;
16
17          use Type::Library
18             -base,
19             -declare => qw( Datetime DatetimeHash EpochHash );
20          use Type::Utils -all;
21          use Types::Standard -types;
22
23          class_type Datetime, { class => "DateTime" };
24
25          declare DatetimeHash,
26             as Dict[
27                year       => Int,
28                month      => Optional[ Int ],
29                day        => Optional[ Int ],
30                hour       => Optional[ Int ],
31                minute     => Optional[ Int ],
32                second     => Optional[ Int ],
33                nanosecond => Optional[ Int ],
34                time_zone  => Optional[ Str ],
35             ];
36
37          declare EpochHash,
38             as Dict[ epoch => Int ];
39
40          coerce Datetime,
41             from Int,          via { "DateTime"->from_epoch(epoch => $_) },
42             from Undef,        via { "DateTime"->now },
43             from DatetimeHash, via { "DateTime"->new(%$_) },
44             from EpochHash,    via { "DateTime"->from_epoch(%$_) };
45
46          1;
47

DESCRIPTION

49       Here's a line by line description of what's going on in the type
50       library.
51
52          package Example::Types;
53
54       Type libraries are packages. It is recommended that re-usable type
55       libraries be given a name in the "Types::*" namespace. For application-
56       specific type libraries, assuming your application's namespace is
57       "MyApp::*" then name the type library "MyApp::Types", or if more than
58       one is needed, use the "MyApp::Types::*" namespace.
59
60          use Type::Library
61             -base,
62             -declare => qw( Datetime DatetimeHash EpochHash );
63
64       The "-base" part is used to establish inheritance. It makes
65       "Example::Types" a child class of "Type::Library".
66
67       Declaring the types we're going to define ahead of their definition
68       allows us to use them as barewords later on. (Note that in code which
69       uses our type library, the types will always be available as barewords.
70       The declaration above just allows us to use them within the library
71       itself.)
72
73          use Type::Utils -all;
74
75       Imports some utility functions from Type::Utils. These will be useful
76       for defining our types and the relationships between them.
77
78          use Types::Standard -types;
79
80       Here we import a standard set of type constraints from Types::Standard.
81       There is no need to do this, but it's often helpful to have a base set
82       of types which we can define our own in terms of.
83
84       Note that although we've imported the types to be able to use in our
85       library, we haven't added the types to our library. We've imported
86       "Str", but other people won't be able to re-import "Str" from our
87       library. If you actually want your library to extend another library,
88       do this instead:
89
90          BEGIN { extends "Types::AnotherLibrary" };
91
92       (Note: if your code breaks here when you upgrade from version 0.006 or
93       below, saying that the 'extends' keyword has not been declared, just
94       add '-all' after use Type::Utils.)
95
96       OK, now we're ready to declare a few types.
97
98          class_type Datetime, { class => "DateTime" };
99
100       This creates a type constraint named "Datetime" which is all objects
101       blessed into the DateTime package. Because this type constraint is not
102       anonymous (it has a name), it will be automagically installed into the
103       type library.
104
105       The next two statements declare two further types constraints, using
106       type constraints from the Types::Standard library. Let's look at
107       "EpochHash" in more detail. This is a hashref with one key called
108       "epoch" and a value which is an integer.
109
110          declare EpochHash,
111             as Dict[ epoch => Int ];
112
113       "EpochHash" inherits from the "Dict" type defined in Types::Standard.
114       It equally could have been defined as:
115
116          declare EpochHash,
117             as HashRef[Int],
118             where { scalar(keys(%$_))==1 and exists $_->{epoch} };
119
120       Or even:
121
122          declare EpochHash,
123             where {
124                    ref($_) eq "HASH"
125                and scalar(keys(%$_))==1
126                and exists $_->{epoch}
127             };
128
129       Lastly we set up coercions. It's best to define all your types before
130       you define any coercions.
131
132          coerce Datetime,
133             from Int,          via { "DateTime"->from_epoch(epoch => $_) },
134             from Undef,        via { "DateTime"->now },
135             from DatetimeHash, via { "DateTime"->new(%$_) },
136             from EpochHash,    via { "DateTime"->from_epoch(%$_) };
137
138       These are simply coderefs that will be fired when you want a Datetime,
139       but are given something else. For more information on coercions, see
140       Type::Tiny::Manual::Coercions.
141
142   Using Your Library
143       Use a custom types library just like you would Types::Standard:
144
145          package MyClass;
146          use Moose;
147          use DateTime;
148          use Example::Types qw( Datetime ); # import the custom type
149
150          has 'sometime' => (
151            is      => 'rw',
152            isa     => Datetime,
153            coerce  => 1,
154          );
155
156       Type libraries defined with Type::Library are also able to export some
157       convenience functions:
158
159          use Example::Types qw( is_Datetime to_Datetime assert_Datetime );
160
161          my $dt = Foo::get_datetime;
162
163          unless ( is_Datetime $dt )
164          {
165             $dt = to_Datetime $dt;
166          }
167
168          assert_Datetime $dt;
169
170       These functions act as shortcuts for:
171
172          use Example::Types qw( Datetime );
173
174          my $dt = Foo::get_datetime;
175
176          unless ( Datetime->check($dt) )
177          {
178             $dt = Datetime->coerce($dt);
179          }
180
181          Datetime->assert_return($dt);
182
183       Pick whichever style you think is clearer!
184
185       Type::Library-based libraries provide a shortcut for importing a type
186       constraint along with all its associated convenience functions:
187
188          # Shortcut for qw( DateTime is_Datetime to_Datetime assert_Datetime )
189          #
190          use Example::Types qw( +Datetime );
191
192       See Type::Tiny::Manual for other ways to make use of type libraries.
193

ADVANCED TOPICS

195   Messages
196       It is sometimes nice to be able to emit a more useful error message
197       than the standard:
198
199          Value "Foo" did not pass type constraint "Bar"
200
201       It is possible to define custom error messages for types.
202
203          declare MediumInteger, as Integer,
204             where   { $_ >= 10 and $_ < 20 },
205             message {
206                return Integer->get_message($_) if !Integer->check($_);
207                return "$_ is too small!"       if $_ < 10;
208                return "$_ is so very, very big!";
209             };
210
211   Parameterized Constraints
212       Parameterized type constraints are those that can generate simple child
213       type constraints by passing parameters to their "parameterize" method.
214       For example, ArrayRef in Types::Standard:
215
216          use Types::Standard;
217
218          my $ArrayRef         = Types::Standard::ArrayRef;
219          my $Int              = Types::Standard::Int;
220          my $ArrayRef_of_Ints = $ArrayRef->parameterize($Int);
221
222       Type libraries provide some convenient sugar for this:
223
224          use Types::Standard qw( ArrayRef Int );
225
226          my $ArrayRef_of_Ints = ArrayRef[Int];
227
228       Unlike Moose which has separate meta classes for parameterizable,
229       parameterized and non-parameterizable type constraints, Type::Tiny
230       handles all that in one.
231
232       To create a parameterizable type constraint, you'll need to pass an
233       extra named parameter to "declare". Let's imagine that we want to make
234       our earlier "NonEmptyHash" constraint accept a parameter telling it the
235       minimum size of the hash. For example "NonEmptyHash[4]" would need to
236       contain at least four key-value pairs. Here's how you'd do it:
237
238          declare NonEmptyHash, as HashLike,
239             where     { scalar values %$_ },
240             inline_as {
241                my ($constraint, $varname) = @_;
242                return sprintf(
243                   '%s and scalar values %%{%s}',
244                   $constraint->parent->inline_check($varname),
245                   $varname,
246                );
247             },
248             # Generate a new "where" coderef...
249             constraint_generator => sub {
250                my ($minimum) = @_;
251                die "parameter must be positive" unless int($minimum) > 0;
252                return sub {
253                    scalar(values(%$_)) >= int($minimum);
254                };
255             },
256             # Generate a new "inline_as" coderef...
257             inline_generator => sub {
258                my ($minimum) = @_;
259                return sub {
260                   my ($constraint, $varname) = @_;
261                   return sprintf(
262                      '%s and scalar(values(%%{%s})) >= %d',
263                      $constraint->parent->inline_check($varname),
264                      $varname,
265                      $minimum,
266                   );
267                };
268             };
269

SEE ALSO

271       Some type libraries on CPAN:
272
273       ·   Types::Standard
274
275       ·   Types::Path::Tiny
276
277       ·   Types::XSD / Types::XSD::Lite
278
279       ·   Types::Set
280
281       ·   more <https://github.com/tobyink/p5-type-tiny/wiki/Type-libraries>!
282

AUTHOR

284       Toby Inkster <tobyink@cpan.org>.
285
287       This software is copyright (c) 2013-2014, 2017-2019 by Toby Inkster.
288
289       This is free software; you can redistribute it and/or modify it under
290       the same terms as the Perl 5 programming language system itself.
291

DISCLAIMER OF WARRANTIES

293       THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
294       WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
295       MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
296
297
298
299perl v5.30.0                      2019-07-26  Type::Tiny::Manual::Libraries(3)
Impressum