Type::T...thOther(3)
π Type::Tiny::Manual::UsingWithOther π
okay so bestie, real talk: this one lives in the User Contributed Perl Documentation manual set, and it's all about using Type::Tiny with Class::InsideOut, Params::Check, and Object::Accessor. Buckle up, it's giving β¨ niche but useful β¨.
πΈ NAME πΈ
Type::Tiny::Manual::UsingWithOther β using Type::Tiny with Class::InsideOut, Params::Check, and Object::Accessor.
π¦ MANUAL π¦
The antlers crew aren't the only object-oriented programming toolkits in Perl town, bestie. Type::Tiny might have been built with Moose, Mouse, and Moo in mind, but it can absolutely be used with other toolkits too. π«Ά
These toolkits are... well... hmm... okay... they exist. π
Lowkey though: if you're starting a new project, there's very little reason not to use Class::Tiny, Moo, or Moose. So you're probably okay to skip this whole part of the fine manual and go straight to Type::Tiny::Manual::UsingWithTestMore. Periodt. π
π Class::InsideOut π
You want Class::InsideOut 1.13 or above, because that version has support for blessed and overloaded objects (including Type::Tiny type constraints, iconic behavior) for the "get_hook" and "set_hook" options. No cap. π
package Person {
use Class::InsideOut qw( public );
use Types::Standard qw( Str Int );
use Types::Common::Numeric qw( PositiveInt );
use Type::Params qw( signature_for );
# Type checks are really easy.
# Just supply the type as a set hook.
public name => my %_name, {
set_hook => Str,
};
# Define a type that silently coerces negative values
# to positive. It's silly, but it works as an example!
my $Years = PositiveInt->plus_coercions(Int, q{ abs($_) });
# Coercions are more annoying, but possible.
public age => my %_age, {
set_hook => sub { $_ = $Years->assert_coerce($_) },
};
# Parameter checking for methods is as expected.
signature_for get_older => ( method => 1, positional => [ $Years ] );
sub get_older ( $self, $years ) {
$self->_set_age( $self->age + $years );
}
}
π Params::Check and Object::Accessor π
The Params::Check allow() function, the "allow" option for the Params::Check check() function, and the input validation mechanism for Object::Accessor all work the same way, which is basically a limited pure-Perl implementation of the smart match operator. It doesn't directly support Type::Tiny constraints, but it does support coderefs β so you can use Type::Tiny's "compiled_check" method to obtain a suitable coderef. Slay. β¨
Param::Check example:
my $tmpl = {
name => { allow => Str->compiled_check },
age => { allow => Int->compiled_check },
};
check($tmpl, { name => "Bob", age => 32 })
or die Params::Check::last_error();
Object::Accessor example:
my $obj = Object::Accessor->new;
$obj->mk_accessors(
{ name => Str->compiled_check },
{ age => Int->compiled_check },
);
β οΈ Caveat, bestie, pay attention:Object::Accessordoesn't die when a value fails to meet its type constraint; instead it outputs a warning toSTDERR. This behaviour can be changed by setting"$Object::Accessor::FATAL = 1". π
π§ Class::Struct π§
This is a proof-of-concept of how Type::Tiny can be used to constrain attributes for Class::Struct. It's probably not a good idea to use this in production, because it slows down "UNIVERSAL::isa" globally. Like, globally globally. π
use Types::Standard -types;
use Class::Struct;
{
my %MAP;
my $orig_isa = \&UNIVERSAL::isa;
*UNIVERSAL::isa = sub {
return $MAP{$1}->check($_[0])
if $_[1] =~ /^CLASSSTRUCT::TYPETINY::(.+)$/ && exists $MAP{$1};
goto $orig;
};
my $orig_dn = \&Type::Tiny::display_name;
*Type::Tiny::display_name = sub {
if (caller(1) eq 'Class::Struct') {
$MAP{$_[0]{uniq}} = $_[0];
return "CLASSSTRUCT::TYPETINY::".$_[0]{uniq};
}
goto $orig_dn;
};
}
struct Person => [ name => Str, age => Int ];
my $bob = Person->new(
name => "Bob",
age => 21,
);
$bob->name("Robert"); # okay
$bob->name([]); # dies
π Class::Plain π
There is not currently a high level of integration, but here's a quick example of type checking attributes in the constructor. π«Ά
Heads up: if any of your accessors are ":rw" then you would also need to add type checks to those. iykyk.
use Class::Plain;
class Point {
use Types::Common -types, -sigs;
field x :reader;
field y :reader;
signature_for new => (
method => !!1,
bless => !!0,
named => [
x => Int,
y => Int,
],
);
method as_arrayref () {
return [ $self->x, $self->y ];
}
}
The following signature may also be of interest:
signature_for new => (
method => !!1,
multiple => [
{
named => [
x => Int,
y => Int,
],
bless => !!0,
},
{
positional => [ Int, Int ],
goto_next => sub {
my ( $class, $x, $y ) = @_;
return ( $class, { x => $x, y => $y } ),
},
},
],
);
This would allow your class to be instantiated using any of the following:
my $point11 = Point->new( { x => 1, y => 1 } );
my $point22 = Point->new( x => 2, y => 2 );
my $point33 = Point->new( 3, 3 );
β NEXT STEPS β
Here's your next step, bestie:
Type::Tiny::Manual::UsingWithTestMoreβ Type::Tiny for test suites. πΈ
π AUTHOR π
Toby Inkster <tobyink@cpan.org>.
π COPYRIGHT AND LICENCE π
This software is copyright (c) 2013-2014, 2017-2025 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.
and that's the whole page, bestie!! π¦β¨ this one came from perl v5.42.0, dated 2026-01-17 β go forth and type-check responsibly πππ
π¦ where this page comes from
- fedora 44: perl-Type-Tiny 2.010001-2.fc44 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms