---
name: "Bread::Board::Manual::Concepts::Typemap"
section: "3pm"
platform: "linux"
package: "libbread-board-perl"
version: "0.37-2"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/Bread::Board::Manual::Concepts::Typemap"
---

# Bread::Board::Manual::Concepts::Typemap(3pm)

An overview of the typemapping feature

## NAME

Bread::Board::Manual::Concepts::Typemap - An overview of the typemapping feature

## VERSION

version 0.37

## INTRODUCTION

A new (read: experimental) feature of Bread::Board is typemapped services. These are services which are mapped to a particular type rather then just a name. This feature has the potential to make obsolete a large amount of the Bread::Board configuration by simply asking Bread::Board to figure things out on its own. Here is a small example of how this works.

```
  # define the classes making sure
  # to specify required items and
  # their types
  {
      package Stapler;
      use Moose;
      package Desk;
      use Moose;
      package Chair;
      use Moose;
      package Cubicle;
      use Moose;
      has 'desk'  => ( is => 'ro', isa => 'Desk',  required => 1 );
      has 'chair' => ( is => 'ro', isa => 'Chair', required => 1 );
      package Employee;
      use Moose;
      has [ 'first_name', 'last_name' ] => (
          is       => 'ro',
          isa      => 'Str',
          required => 1,
      );
      has 'stapler' => ( is => 'rw', isa => 'Stapler', predicate => 'has_stapler' );
      has 'work_area' => ( is => 'ro', isa => 'Cubicle', required => 1 );
  }
  # now create the container, and
  # map the Employee type and ask
  # Bread::Board to infer all the
  # other relationships
  my $c = container 'Initech' => as {
      typemap 'Employee' => infer;
  };
  # now you can create new Employee objects
  # by calling ->resolve with the type and
  # supplying the required parameters (see
  # below for details).
  my $micheal = $c->resolve(
      type       => 'Employee',
      parameters => {
          first_name => 'Micheal',
          last_name  => 'Bolton'
      }
  );
  my $cube = $micheal->work_area; # this will be a Cubicle object
  $cube->desk;  # this will be a Desk object
  $cube->chair; # this will be a Chair object
  $micheal->has_stapler; # this is false
  # We can create another Employee object
  # and this time we pass in the optional
  # parameter for the non-required 'stapler'
  # attribute
  my $milton = $c->resolve(
      type       => 'Employee',
      parameters => {
          first_name => 'Milton',
          last_name  => 'Waddams',
          stapler    => Stapler->new
      }
  );
  $milton->has_stapler; # this is true
```

In the above example, we created a number of Moose classes that had specific required relationships. When we called `"infer"` for the **Employee** object, Bread::Board figured out those relationships and set up dependencies and parameters accordingly.

For the `"work_area"` object, we saw the **Cubicle** type and then basically called `"infer"` on the **Cubicle** object. We then saw the **Desk** and **Chair** objects and called `"infer"` on those as well. The result of this recursive inference was that the **Employee**, **Cubicle**, **Desk** and **Chair** relationships were modeled in Bread::Board as dependent services.

Bread::Board also took it one step further.

We were able to resolve the **Cubicle**, **Desk** and **Chair** types automatically because they were already defined by Moose as subtypes of the *Object* type. We knew that it could introspect those classes and get more information. However, this was not the case with the *first\_name* and *last\_name* attributes of the **Employee** object. In that case, we determined that we couldn't resolve those objects and (because it was a top-level inference) instead turned them into required parameters for the inferred **Employee** service.

And lastly, with a top-level inference (not one caused by recursion) Bread::Board will also look at all the remaining non-required attributes and turn them into optional parameters. In this case we have a `"stapler"` attribute that is not required and so is listed as an optional parameter, meaning that it is not required, but still subject to type checking.

## CONCLUSION

This example should give a good basic overview of this feature and more details can be found in the test suite (*t/07\*.t*). These show examples of how to typemap roles to concrete classes and how to supply hints to `"infer"` to help Bread::Board figure out specific details.

As I mentioned above, this feature should be considered experimental and we are still working out details and writing tests for it. Any contributions are welcome.

## AUTHOR

Stevan Little \<stevan@iinteractive.com\>

## BUGS

Please report any bugs or feature requests on the bugtracker website https://github.com/stevan/BreadBoard/issues

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.

## COPYRIGHT AND LICENSE

This software is copyright (c) 2019, 2017, 2016, 2015, 2014, 2013, 2011, 2009 by Infinity Interactive.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
