Type::Tiny::Duck(3)

✨ Type::Tiny::Duck ✨

okay so bestie, welcome to Type::Tiny::Duck β€” it's the part of the Type::Tiny family (you'll find it in the perl manual pages, section 3) that does type constraints based on the can method. duck typing, but make it fashion πŸ¦†πŸ’…


🌸 NAME 🌸

Type::Tiny::Duck β€” type constraints based on the can method. that's it, that's the whole vibe.


πŸŽ€ SYNOPSIS πŸŽ€

so there's like three ways to do this and honestly? all of them eat. 🍽️

way one: using via Types::Standard

package Logger {
  use Moo;
  use Types::Standard qw( HasMethods Bool );

  has debugging => ( is => 'rw', isa => Bool, default => 0 );
  has output    => ( is => 'ro', isa => HasMethods[ 'print' ] );

  sub warn {
    my ( $self, $message ) = @_;
    $self->output->print( "[WARNING] $message\n" );
  }

  sub debug {
    my ( $self, $message ) = @_;
    $self->output->print( "[DEBUG] $message\n" ) if $self->debugging;
  }
}

way two: using Type::Tiny::Duck's export feature

package Logger {
  use Moo;
  use Types::Standard qw( Bool );
  use Type::Tiny::Duck Printable => [ 'print' ];

  has debugging => ( is => 'rw', isa => Bool, default => 0 );
  has output    => ( is => 'ro', isa => Printable );

  sub warn {
    my ( $self, $message ) = @_;
    $self->output->print( "[WARNING] $message\n" );
  }

  sub debug {
    my ( $self, $message ) = @_;
    $self->output->print( "[DEBUG] $message\n" ) if $self->debugging;
  }
}

way three: using Type::Tiny::Duck's object-oriented interface

package Logger {
  use Moo;
  use Types::Standard qw( Bool );
  use Type::Tiny::Duck;

  my $Printable = Type::Type::Duck->new(
    name    => 'Printable',
    methods => [ 'print' ],
  );

  has debugging => ( is => 'rw', isa => Bool, default => 0 );
  has output    => ( is => 'ro', isa => $Printable );

  sub warn {
    my ( $self, $message ) = @_;
    $self->output->print( "[WARNING] $message\n" );
  }

  sub debug {
    my ( $self, $message ) = @_;
    $self->output->print( "[DEBUG] $message\n" ) if $self->debugging;
  }
}
not me side-eyeing that third block πŸ‘€ β€” yes, Type::Type::Duck->new is what the docs say, character for character, so that's what you're getting. i don't make the rules, i just transcribe them faithfully. πŸ™ˆ

⭐ STATUS ⭐

this module is covered by the Type-Tiny stability policy. it's official, it's vetted, it's got its papers. πŸ’œ


πŸ¦‹ DESCRIPTION πŸ¦‹

type constraints of the general form { $_->can("method") }. literally just vibes-checking that your object can do the thing. ✨

the name comes from the saying: "If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck". duck typing is lowkey a more flexible way of testing objects than relying on isa, because it lets people swap in mock objects with zero drama. no cap. πŸ¦†

this package inherits from Type::Tiny; go read that for most of the documentation. the major differences are right here:

πŸ”¨ Constructors πŸ”¨

the new constructor from Type::Tiny still works, of course. obviously. but there's also this one:

  • new_intersection( type_constraints => \@ducklings, %opts ) β€” makes a brand-new duck type constraint that's the intersection of existing duck type constraints. so instead of building some complex union type constraint with two duck type constraints as its children, you can just take HasMethods['read'] and HasMethods['write'] and smash them into HasMethods['read', 'write']. iconic behavior, honestly. πŸ’…

πŸ’Ž Attributes πŸ’Ž

  • methods β€” an arrayref of method names. the whole to-do list of what your object gotta be able to do. πŸ“
  • constraint β€” unlike Type::Tiny, you cannot pass a constraint coderef to the constructor here. nope. rely on the default instead. πŸ™…
  • inlined β€” unlike Type::Tiny, you cannot pass an inlining coderef to the constructor here either. rely on the default. same energy. πŸ™…
  • parent β€” parent is always Types::Standard::Object, and it cannot be passed to the constructor. it's not up for discussion, it's set in stone. πŸͺ¨

🧚 Methods 🧚

  • stringifies_to($constraint) β€” see Type::Tiny::ConstrainedObject.
  • numifies_to($constraint) β€” see Type::Tiny::ConstrainedObject.
  • with_attribute_values($attr1 => $constraint1, ...) β€” see Type::Tiny::ConstrainedObject.

🎁 Exports 🎁

Type::Tiny::Duck can be used as an exporter. slay.

use Type::Tiny::Duck HttpClient => [ 'get', 'post' ];

this will export the following functions into your namespace:

  • HttpClient
  • is_HttpClient( $value )
  • assert_HttpClient( $value )
  • to_HttpClient( $value )

and you can export multiple types at once, because why settle for one:

use Type::Tiny::Duck (
  HttpClient   => [ 'get', 'post' ],
  FtpClient    => [ 'upload', 'download' ],
);

πŸ’€ BUGS πŸ’€

found a bug? bestie, please report it β€” head to https://github.com/tobyink/p5-type-tiny/issues. 🫢


πŸ‘‘ SEE ALSO πŸ‘‘

  • Type::Tiny::Manual.
  • Type::Tiny.
  • Moose::Meta::TypeConstraint::DuckType.

🌈 AUTHOR 🌈

Toby Inkster <tobyink@cpan.org>. the main character, fr fr. πŸ‘‘


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.

like, no promises. you get what you get. πŸ’€


perl v5.42.0 Β· 2026-01-17 Β· Type::Tiny::Duck(3) β€” that's the version and the date, babes, and this has been your girl walking you through duck typing in section 3 of the manual. go forth and can things. πŸ¦‹βœ¨πŸ’œ

πŸ“¦ where this page comes from