Skip to content

Effects Composition

The Typed IDs module is not an effects module itself — it has no runtime behavior. However, typed IDs serve as the identity foundation for two core effects modules: Data Store and Event Store.

Data Store Integration

The Data Store module uses typed IDs as primary keys for stored entities. A [StoredEntity] must have at least one property whose type is decorated with [TypedId] — the generator discovers it automatically.

using Deepstaging.DataStore;
using Deepstaging.Ids;

[TypedId(Converters = IdConverters.EfCoreValueConverter)]
public readonly partial struct ArticleId;

[StoredEntity]
public partial record Article(ArticleId Id, string Title, string Body);

[DataStore]
public static partial class AppStore;

The generated store interface uses the typed ID for lookups:

// Generated: AppStore.Articles.GetAsync(ArticleId id, ...)
var article = await store.Articles.GetAsync(articleId);

Tip

Enable IdConverters.EfCoreValueConverter on IDs used with Data Store so EF Core can persist them without manual configuration.

Event Store Integration

The Event Store module uses [StreamId]-decorated typed IDs to identify event streams for aggregates. An [EventSourcedAggregate] must have a property whose type carries [StreamId].

using Deepstaging.EventStore;
using Deepstaging.Ids;

[TypedId]
[StreamId]
public readonly partial struct OrderId;

public sealed record OrderCreated(OrderId OrderId, string CustomerName) : IAggregateEvent;

[EventSourcedAggregate]
public partial record Order(OrderId Id, string CustomerName, int ItemCount)
{
    public static Order Create(OrderCreated e) =>
        new(e.OrderId, e.CustomerName, 0);
}

[EventStore]
public static partial class AppEventStore;

The generated StreamName property and FromStreamName parser enable the event store to map between typed IDs and stream names:

var id = OrderId.New();
id.StreamName;                     // "order-550e8400-e29b-41d4-a716-446655440000"
OrderId.FromStreamName("order-…"); // parses back to OrderId

See the Attributes reference for [StreamId] configuration options.

EF Core Value Converter

When persisting typed IDs through EF Core — whether via Data Store or standalone — enable the EfCoreValueConverter flag:

[TypedId(Converters = IdConverters.EfCoreValueConverter)]
public readonly partial struct CustomerId;

This generates a nested ValueConverter<CustomerId, Guid> class. See the Converters page for full details on generated converter classes, DbContext configuration, and convention-based registration.