Value-Type Design
An Stdb.* value type wraps an Effect schema rather than being a plain schema.
That design is deliberate: SpaceTimeDB declaration sites must reject raw Effect
schemas at compile time, while application code still needs ordinary schemas for
decode, encode, HTTP bodies, and domain logic.
The Two Jobs
Section titled “The Two Jobs”A value type must:
- Reuse an Effect schema for TypeScript values and JSON codecs.
- Carry SpaceTimeDB SATS information so tables, params, returns, and errors lower to native types.
Effect annotations preserve runtime metadata, but TypeScript cannot see whether a schema has a particular annotation. Phantom type markers on schemas are also fragile because Effect transforms rebuild schema types and strip the marker.
Chosen Tradeoff
Section titled “Chosen Tradeoff”effect-spacetimedb uses an opaque wrapper. The wrapper is not itself a schema;
unwrap with .schema when ordinary Effect schema interop is required.
This keeps one important guarantee: raw schemas are rejected in SATS positions at compile time. It also avoids “tag must be last” bugs where a refinement or brand accidentally strips a marker.
Recommended Pattern
Section titled “Recommended Pattern”For branded domain values, keep the raw Effect schema as the source of truth and wrap it inline at SpaceTimeDB boundaries:
const UserId = Schema.String.pipe(Schema.brand("UserId"))
Stdb.string(UserId) // table fields, params, returns, error fieldsFor generic SATS values reused across many fields, keep a value-type alias:
const ShortString = Stdb.string(Schema.String.pipe(Schema.minLength(1)))Not affiliated with SpacetimeDB (Clockwork Laboratories) or Effect (Effectful Technologies).