stampit API
  • Introduction
  • Essentials
    • What is a Stamp
    • Installation
    • Specification
      • Merging algorithm
      • Object creation internals
    • FAQ
  • API
    • Quick start
    • Basics
    • Methods
    • Properties
    • Deep properties
    • Initializers
    • Static properties
    • Static deep properties
    • Configuration
    • Deep configuration
    • Composers
    • Property descriptors
    • Static property descriptors
    • Name
  • Ecosystem
    • Ecosystem Overview
    • @stamp/collision
    • @stamp/required
    • @stamp/privatize
    • @stamp/named (DEPRECATED)
    • @stamp/instanceof
Powered by GitBook
On this page
  • Stamp's metadata (descriptor)
  • Ducktyping a stamp
  • Composing stamps
  • Naming conflict resolution
  • Creating stamps
  1. Essentials

What is a Stamp

PreviousIntroductionNextInstallation

Last updated 6 years ago

Stamp is a composable factory function.

NOTE

Factory functions create and return new objects.

Go to to learn how to create a Stamp.

const object = Stamp() // creating a new object from a stamp

Stamp's metadata (descriptor)

But unlike plain functions, Stamps carry around the metadata about the object they are going to produce. The metadata is attached to the Stamp.compose object. Another name for that metadata is "stamp descriptor" or just "descriptor".

const descriptor = Stamp.compose // retrieving a stamp's metadata

There are 11 types of metadata:

interface Descriptor {
  methods: Object,
  properties: Object,
  deepProperties: Object,
  propertyDescriptors: Object,
  initializers: Function[],
  staticProperties: Object,
  staticDeepProperties: Object,
  staticPropertyDescriptors: Object,
  composers: Function[],
  configuration: Object,
  deepConfiguration: Object
}

You, the developer, is allowed and encouraged to operate that metadata manually if needed.

For example, you can always check which methods an object instance will have:

console.log('Object will have these methods:', Object.keys(Stamp.compose.methods))

Ducktyping a stamp

To understand if your object is a stamp you need to check its property .compose like this:

function isStamp (object) {
  return typeof object === 'function' && typeof object.compose === 'function'
}

Composing stamps

The main reason why stamps exist is the ability to freely compose stamps together.

const ComposedStamp = stampit(Stamp1, Stamp2, Stamp3)

The line above is identical to these:

const ComposedStamp = Stamp1.compose(Stamp2, Stamp3)
const ComposedStamp = Stamp1.compose(Stamp2).compose(Stamp3)
const ComposedStamp = Stamp1.compose(Stamp2.compose(Stamp3))
const ComposedStamp = stampit().compose(Stamp1, Stamp2, Stamp3)

NOTE

Every time you call stampit or .compose you create a NEW stamp.

Naming conflict resolution

There is no naming conflict resolution in stamps by default. This means that in case of conflicting properties/methods the last composed overwrites all previous.

const Stamp1 = stampit({ prop: { conflicting: 'foo' } })
const Stamp2 = stampit({ prop: { conflicting: 'oops!!!' } })

const ComposedStamp = compose(Stamp1, Stamp2)
ComposedStamp.compose.properties.conflicting === 'oops!!!'

const ReverseComposedStamp = compose(Stamp2, Stamp1)
ReverseComposedStamp.compose.properties.conflicting === 'foo'

This behaviour is by design.

NOTE

Creating stamps

To create a new stamp from scratch you would need to use one of the JavaScript modules available:

You can use both stampits same way as if it was the compose function. But you cannot use compose function same way as stampit. For example, these lines generate same stamp:

const StampFromCompose = compose(Stamp1, Stamp2, Stamp3)
const StampFromStampit = stampit(Stamp1, Stamp2, Stamp3)

However, stampit adds few more handy APIs to your stamp (see comments):

const NewStamp1 = StampFromStampit.methods({ myMethod () {} }) // add a method metadata using chaining API
const NewStamp2 = stampit({ props: { myProperty: 'my value' } }) // using "props" metadata shortcut
// etc

Whereas compose does not have the handy API (see comments):

StampFromCompose.methods === undefined // THERE IS NO .methods CHAINING API
compose({ props: { myProperty: 'my value' } }) // WRONG! YOU MUST USE FULL `properties` KEY

NOTE

The stampit and .compose functions are doing only one thing: merge stamp descriptors according to the .

If you really need to make sure none overwrites your method you can use stamp. Compose it into your stamp. However, in our practice stamps tend to stay quite small, so that conflict resolution is never needed.

- the

- the same as the compose function above, but provides some additional nicer API

- the same as the @stamp/it above, but optimized for browsers

The stampit nicer API is nothing else but few additional in your stamps. That's it.

API Quick start
standardized
stamp specification
@stamp/collision
@stamp/compose
standardized compose function
@stamp/it
stampit
static methods