1Moose::Manual::Types(3)User Contributed Perl DocumentatioMnoose::Manual::Types(3)
2
3
4
6 Moose::Manual::Types - Moose's type system
7
9 version 2.2203
10
12 Moose provides its own type system for attributes. You can also use
13 these types to validate method parameters with the help of a MooseX
14 module.
15
16 Moose's type system is based on a combination of Perl 5's own implicit
17 types and some Perl 6 concepts. You can create your own subtypes with
18 custom constraints, making it easy to express any sort of validation.
19
20 Types have names, and you can re-use them by name, making it easy to
21 share types throughout a large application.
22
23 However, this is not a "real" type system. Moose does not magically
24 make Perl start associating types with variables. This is just an
25 advanced parameter checking system which allows you to associate a name
26 with a constraint.
27
28 That said, it's still pretty damn useful, and we think it's one of the
29 things that makes Moose both fun and powerful. Taking advantage of the
30 type system makes it much easier to ensure that you are getting valid
31 data, and it also contributes greatly to code maintainability.
32
34 The basic Moose type hierarchy looks like this
35
36 Any
37 Item
38 Bool
39 Maybe[`a]
40 Undef
41 Defined
42 Value
43 Str
44 Num
45 Int
46 ClassName
47 RoleName
48 Ref
49 ScalarRef[`a]
50 ArrayRef[`a]
51 HashRef[`a]
52 CodeRef
53 RegexpRef
54 GlobRef
55 FileHandle
56 Object
57
58 In practice, the only difference between "Any" and "Item" is
59 conceptual. "Item" is used as the top-level type in the hierarchy.
60
61 The rest of these types correspond to existing Perl concepts. In
62 particular:
63
64 • "Bool" accepts 1 for true, and undef, 0, or the empty string as
65 false.
66
67 • "Maybe[`a]" accepts either "`a" or "undef".
68
69 • "Num" accepts integers, floating point numbers (both in decimal
70 notation & exponential notation), 0, .0, 0.0 etc. It doesn't accept
71 numbers with whitespace, Inf, Infinity, "0 but true", NaN & other
72 such strings.
73
74 • "ClassName" and "RoleName" accept strings that are either the name
75 of a class or the name of a role. The class/role must already be
76 loaded when the constraint is checked.
77
78 • "FileHandle" accepts either an IO::Handle object or a builtin perl
79 filehandle (see "openhandle" in Scalar::Util).
80
81 • "Object" accepts any blessed reference.
82
83 The types followed by "[`a]" can be parameterized. So instead of just
84 plain "ArrayRef" we can say that we want "ArrayRef[Int]" instead. We
85 can even do something like "HashRef[ArrayRef[Str]]".
86
87 The "Maybe[`a]" type deserves a special mention. Used by itself, it
88 doesn't really mean anything (and is equivalent to "Item"). When it is
89 parameterized, it means that the value is either "undef" or the
90 parameterized type. So "Maybe[Int]" means an integer or "undef".
91
92 For more details on the type hierarchy, see
93 Moose::Util::TypeConstraints.
94
96 It's important to realize that types are not classes (or packages).
97 Types are just objects (Moose::Meta::TypeConstraint objects, to be
98 exact) with a name and a constraint. Moose maintains a global type
99 registry that lets it convert names like "Num" into the appropriate
100 object.
101
102 However, class names can be type names. When you define a new class
103 using Moose, it defines an associated type name behind the scenes:
104
105 package MyApp::User;
106
107 use Moose;
108
109 Now you can use 'MyApp::User' as a type name:
110
111 has creator => (
112 is => 'ro',
113 isa => 'MyApp::User',
114 );
115
116 However, for non-Moose classes there's no magic. You may have to
117 explicitly declare the class type. This is a bit muddled because Moose
118 assumes that any unknown type name passed as the "isa" value for an
119 attribute is a class. So this works:
120
121 has 'birth_date' => (
122 is => 'ro',
123 isa => 'DateTime',
124 );
125
126 In general, when Moose is presented with an unknown name, it assumes
127 that the name is a class:
128
129 subtype 'ModernDateTime'
130 => as 'DateTime'
131 => where { $_->year() >= 1980 }
132 => message { 'The date you provided is not modern enough' };
133
134 has 'valid_dates' => (
135 is => 'ro',
136 isa => 'ArrayRef[DateTime]',
137 );
138
139 Moose will assume that "DateTime" is a class name in both of these
140 instances.
141
143 Moose uses subtypes in its built-in hierarchy. For example, "Int" is a
144 child of "Num".
145
146 A subtype is defined in terms of a parent type and a constraint. Any
147 constraints defined by the parent(s) will be checked first, followed by
148 constraints defined by the subtype. A value must pass all of these
149 checks to be valid for the subtype.
150
151 Typically, a subtype takes the parent's constraint and makes it more
152 specific.
153
154 A subtype can also define its own constraint failure message. This lets
155 you do things like have an error "The value you provided (20), was not
156 a valid rating, which must be a number from 1-10." This is much
157 friendlier than the default error, which just says that the value
158 failed a validation check for the type. The default error can, however,
159 be made more friendly by installing Devel::PartialDump (version 0.14 or
160 higher), which Moose will use if possible to display the invalid value.
161
162 Here's a simple (and useful) subtype example:
163
164 subtype 'PositiveInt',
165 as 'Int',
166 where { $_ > 0 },
167 message { "The number you provided, $_, was not a positive number" };
168
169 Note that the sugar functions for working with types are all exported
170 by Moose::Util::TypeConstraints.
171
173 Type names are global throughout the current Perl interpreter.
174 Internally, Moose maps names to type objects via a registry.
175
176 If you have multiple apps or libraries all using Moose in the same
177 process, you could have problems with collisions. We recommend that you
178 prefix names with some sort of namespace indicator to prevent these
179 sorts of collisions.
180
181 For example, instead of calling a type "PositiveInt", call it
182 "MyApp::Type::PositiveInt" or "MyApp::Types::PositiveInt". We recommend
183 that you centralize all of these definitions in a single package,
184 "MyApp::Types", which can be loaded by other classes in your
185 application.
186
187 However, before you do this, you should look at the MooseX::Types
188 module. This module makes it easy to create a "type library" module,
189 which can export your types as perl constants.
190
191 has 'counter' => (is => 'rw', isa => PositiveInt);
192
193 This lets you use a short name rather than needing to fully qualify the
194 name everywhere. It also allows you to easily create parameterized
195 types:
196
197 has 'counts' => (is => 'ro', isa => HashRef[PositiveInt]);
198
199 This module will check your names at compile time, and is generally
200 more robust than the string type parsing for complex cases.
201
203 A coercion lets you tell Moose to automatically convert one type to
204 another.
205
206 subtype 'ArrayRefOfInts',
207 as 'ArrayRef[Int]';
208
209 coerce 'ArrayRefOfInts',
210 from 'Int',
211 via { [ $_ ] };
212
213 You'll note that we created a subtype rather than coercing
214 "ArrayRef[Int]" directly. It's a bad idea to add coercions to the raw
215 built in types.
216
217 Coercions are global, just like type names, so a coercion applied to a
218 built in type is seen by all modules using Moose types. This is another
219 reason why it is good to namespace your types.
220
221 Moose will never try to coerce a value unless you explicitly ask for
222 it. This is done by setting the "coerce" attribute option to a true
223 value:
224
225 package Foo;
226
227 has 'sizes' => (
228 is => 'ro',
229 isa => 'ArrayRefOfInts',
230 coerce => 1,
231 );
232
233 Foo->new( sizes => 42 );
234
235 This code example will do the right thing, and the newly created object
236 will have "[ 42 ]" as its "sizes" attribute.
237
238 Deep coercion
239 Deep coercion is the coercion of type parameters for parameterized
240 types. Let's take these types as an example:
241
242 subtype 'HexNum',
243 as 'Str',
244 where { /[a-f0-9]/i };
245
246 coerce 'Int',
247 from 'HexNum',
248 via { hex $_ };
249
250 has 'sizes' => (
251 is => 'ro',
252 isa => 'ArrayRef[Int]',
253 coerce => 1,
254 );
255
256 If we try passing an array reference of hex numbers for the "sizes"
257 attribute, Moose will not do any coercion.
258
259 However, you can define a set of subtypes to enable coercion between
260 two parameterized types.
261
262 subtype 'ArrayRefOfHexNums',
263 as 'ArrayRef[HexNum]';
264
265 subtype 'ArrayRefOfInts',
266 as 'ArrayRef[Int]';
267
268 coerce 'ArrayRefOfInts',
269 from 'ArrayRefOfHexNums',
270 via { [ map { hex } @{$_} ] };
271
272 Foo->new( sizes => [ 'a1', 'ff', '22' ] );
273
274 Now Moose will coerce the hex numbers to integers.
275
276 Moose does not attempt to chain coercions, so it will not coerce a
277 single hex number. To do that, we need to define a separate coercion:
278
279 coerce 'ArrayRefOfInts',
280 from 'HexNum',
281 via { [ hex $_ ] };
282
283 Yes, this can all get verbose, but coercion is tricky magic, and we
284 think it's best to make it explicit.
285
287 Moose allows you to say that an attribute can be of two or more
288 disparate types. For example, we might allow an "Object" or
289 "FileHandle":
290
291 has 'output' => (
292 is => 'rw',
293 isa => 'Object | FileHandle',
294 );
295
296 Moose actually parses that string and recognizes that you are creating
297 a type union. The "output" attribute will accept any sort of object, as
298 well as an unblessed file handle. It is up to you to do the right thing
299 for each of them in your code.
300
301 Whenever you use a type union, you should consider whether or not
302 coercion might be a better answer.
303
304 For our example above, we might want to be more specific, and insist
305 that output be an object with a "print" method:
306
307 duck_type 'CanPrint', [qw(print)];
308
309 We can coerce file handles to an object that satisfies this condition
310 with a simple wrapper class:
311
312 package FHWrapper;
313
314 use Moose;
315
316 has 'handle' => (
317 is => 'rw',
318 isa => 'FileHandle',
319 );
320
321 sub print {
322 my $self = shift;
323 my $fh = $self->handle();
324
325 print {$fh} @_;
326 }
327
328 Now we can define a coercion from "FileHandle" to our wrapper class:
329
330 coerce 'CanPrint'
331 => from 'FileHandle'
332 => via { FHWrapper->new( handle => $_ ) };
333
334 has 'output' => (
335 is => 'rw',
336 isa => 'CanPrint',
337 coerce => 1,
338 );
339
340 This pattern of using a coercion instead of a type union will help make
341 your class internals simpler.
342
344 The Moose::Util::TypeConstraints module exports a number of helper
345 functions for creating specific kinds of types. These include
346 "class_type", "role_type", "maybe_type", and "duck_type". See the docs
347 for details.
348
349 One helper worth noting is "enum", which allows you to create a subtype
350 of "Str" that only allows the specified values:
351
352 enum 'RGB', [qw( red green blue )];
353
354 This creates a type named "RGB".
355
357 All of the type creation functions return a type object. This type
358 object can be used wherever you would use a type name, as a parent
359 type, or as the value for an attribute's "isa" option:
360
361 has 'size' => (
362 is => 'ro',
363 isa => subtype( 'Int' => where { $_ > 0 } ),
364 );
365
366 This is handy when you want to create a one-off type and don't want to
367 "pollute" the global namespace registry.
368
370 Moose does not provide any means of validating method parameters.
371 However, there are several MooseX extensions on CPAN which let you do
372 this.
373
374 The simplest and least sugary is Params::ValidationCompiler. This lets
375 you validate a set of named parameters using Moose types:
376
377 use Moose::Util::TypeConstraints qw( find_type_constraint );
378 use Params::ValidationCompiler qw( validation_for );
379
380 {
381 my $validator = validation_for(
382 params => {
383 foo => { type => find_type_constraint('Int') },
384 bar => {
385 type => find_type_constraint('Str'),
386 optional => 1,
387 },
388 baz => {
389 type => find_type_constraint('Int'),
390 default => 42,
391 },
392 },
393 );
394
395 sub foo {
396 my %args = $validator->(@_);
397 }
398 }
399
400 Params::ValidationCompiler also supports coercions.
401
402 There are several more powerful extensions that support method
403 parameter validation using Moose types, including Moops, which gives
404 you a full-blown "method" keyword.
405
406 method morning ( Str $name ) {
407 $self->say("Good morning ${name}!");
408 }
409
411 Because Moose types are defined at runtime, you may run into load order
412 problems. In particular, you may want to use a class's type constraint
413 before that type has been defined.
414
415 In order to ameliorate this problem, we recommend defining all of your
416 custom types in one module, "MyApp::Types", and then loading this
417 module in all of your other modules.
418
420 • Stevan Little <stevan@cpan.org>
421
422 • Dave Rolsky <autarch@urth.org>
423
424 • Jesse Luehrs <doy@cpan.org>
425
426 • Shawn M Moore <sartak@cpan.org>
427
428 • יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
429
430 • Karen Etheridge <ether@cpan.org>
431
432 • Florian Ragwitz <rafl@debian.org>
433
434 • Hans Dieter Pearcey <hdp@cpan.org>
435
436 • Chris Prather <chris@prather.org>
437
438 • Matt S Trout <mstrout@cpan.org>
439
441 This software is copyright (c) 2006 by Infinity Interactive, Inc.
442
443 This is free software; you can redistribute it and/or modify it under
444 the same terms as the Perl 5 programming language system itself.
445
446
447
448perl v5.36.0 2023-02-06 Moose::Manual::Types(3)