Skip to content

Entities

An entity represents a business data structure, composed of several properties. Each property is typed via a NewType.

Example

INFO

In general, it is preferable to define a create() function rather than using the new() function to prevent default value cases.

How it works

C.createEntity(...) returns an entity handler.

This handler gives you two ways to build an entity:

  • map(...) / mapOrThrow(...): from raw properties (e.g. HTTP payload, DB, etc.). Values go through the DataParser of each NewType and the associated constraints.
  • new(...): from already typed properties (useful when you are already in business code).

The created entity can then be identified with is(...) (type guard), which makes narrowing in unions easier.

Define properties

Property definition is done via a callback: you return an object where each key is a business property, and each value is a NewTypeHandler (or an advanced definition).

The callback receives params, which exposes helpers to enrich the definition:

nullable(definition)

Allows null on a property.

array(definition, { min?, max? })

Declares a property as an array, with optional min/max (runtime validation + typing).

When max is declared and you build an entity with new(...), the property must already carry the matching MaxElements type constraint. Use A.withMaxElements on finite tuples to satisfy that contract. This is not needed with map(...) or mapOrThrow(...), because raw arrays are validated and constrained during mapping.

union(...definitions)

Declares a union of several NewTypeHandler for the same property.

structure(definition)

Declares a structured property (object) where each field has its own entity property definition.

Useful to model nested business sub-objects without creating a separate entity.

identifier(definition)

Declares a string literal property (e.g. "profile", "agent") with strict runtime validation.

This helper is meant for technical identification (discrimination, structure version/tag, etc.), not for free-form business data. For business text values, prefer a NewType.

These helpers are combinable (e.g. nullable(array(...)), structure({ type: identifier("agent") })), and they serve both runtime (validation) and typing.

Methods and Properties

An EntityHandler exposes:

Methods

new()

Builds the entity from already typed properties.

typescript
function new(
	properties: Properties
): Entity<EntityName> & Properties

map()

Validates and transforms raw properties into typed properties, then builds the entity. An optional callback can subsequently refine the entity with business rules or add flags to it.

typescript
function map(
	rawProperties: PropertiesToMapOfEntity,
	refineEntity?: (entity: Entity) => Right | Left
): Right<"hydratedEntity", Entity> | Left<"hydrateEntityError", DP.DataParserError> | RefinerResult

function map(
	refineEntity: (entity: Entity) => Right | Left
): (rawProperties: PropertiesToMapOfEntity) => Left<"hydrateEntityError", DP.DataParserError> | RefinerResult

rawProperties is intentionally permissive: some constraints (for example array(..., { min })) are enforced at validation time.

Without a callback, a successful mapping returns Right<"hydratedEntity", Entity>. With a callback, its Right or Left is returned as-is and its precise type is preserved. The callback is not called if hydration fails.

mapOrThrow()

typescript
function mapOrThrow(
	rawProperties: PropertiesToMapOfEntity,
	refineEntity?: (entity: Entity) => Right | Left
): Entity | RefinedEntity

function mapOrThrow(
	refineEntity: (entity: Entity) => Right | Left
): (rawProperties: PropertiesToMapOfEntity) => RefinedEntity

Throws C.HydrateEntityError when the raw properties cannot be hydrated. If the refinement callback returns a Left, the method throws C.RefineEntityError. Otherwise, it directly returns the unwrapped Right value.

Both methods accept the refinement as a second argument or in curried form, notably for use with pipe:

is()

typescript
function is(
	value: unknown
): value is Entity<EntityName>

update()

Updates an existing entity by merging typed properties.

typescript
function update(
	entity: Entity<EntityName>,
	properties: Partial<Properties>
): Entity<EntityName> & Properties

Properties

name

The unique name of the entity (e.g. "User"), used as a runtime identifier.

propertiesDefinition

The properties definition (as declared in createEntity).

Get the type

To retrieve the type of the generated entity:

typescript
type User = C.GetEntity<typeof User>;

See also

Released under the MIT license.