Skip to content

Defining types

By the end of this page the app will have its three types: organizations, the people who work at them, and the events they attend.

A type is a schema with a name. ECHO uses the schema three ways:

  • The compiler uses it to check the fields of every object you create.
  • ECHO uses it to check what it stores, and to send the type to peers that have not seen it.
  • Code can read it at run time. The app’s forms, table and graph are built from the schemas rather than written per type.

The schema is an Effect Schema. The name is a DXN: a reverse-domain name and a version, such as com.example.type.person at 0.1.0. Use a domain you control, since the name is global.

A field can hold a reference to another object, with Ref.Ref(Type). A reference stores the target’s identity, not a copy, so the graph stays consistent when the target changes.

  1. Declare an organization. Type.makeObject takes the name and the schema, and returns a class that is both the schema and the TypeScript type of its instances.

    export class
    class Organization
    Organization
    extends
    import Type
    Type
    .
    const makeObject: <Organization>(dxn: DXN.DXN, options?: {
    id?: EntityId;
    }) => Type.MakeObject<Organization>

    Factory function to create an ECHO object type.

    Returns a Type.Type entity — a live, in-memory TypeSchema instance, NOT a Schema.Schema. Use Type.InstanceType<typeof Foo> for the instance type and Type.getSchema(Foo) to obtain the underlying Effect Schema.

    The entity's id defaults to EntityId.deterministic(typename, version) so constructing a type never reaches crypto.getRandomValues() — required for Cloudflare workerd, which forbids RNG calls in global (module-evaluation) scope. Pass { id } to override (e.g. with EntityId.random() from a request handler).

    Giving the type a nominal class name keeps its inferred type portable for declaration emit: structural expansion (which can pull in unnameable union members from referenced schemas) is replaced by a reference to the class.

    The second call takes either a schema, or struct fields (wrapped in Schema.Struct) with an optional function that pipes annotations onto the struct.

    @example

    export class Person extends Type.makeObject<Person>(DXN.make('com.example.type.myType', '0.1.0'))(Schema.Struct({
    name: Schema.String,
    })) {}
    export class Tag extends Type.makeObject<Tag>(DXN.make('com.example.type.tag', '0.1.0'))(
    { label: Schema.String },
    Annotation.LabelAnnotation.set(['label']),
    ) {}

    @performance ― O(schema size) once at definition time; builds the type entity eagerly, so call it at module scope, not per use.

    makeObject
    <
    class Organization
    Organization
    >(
    import DXN
    DXN
    .
    const make: <"com.example.type.organization">(nsid: "com.example.type.organization", version?: string) => DXN.DXN

    Constructs a DXN from an NSID (and optional version). Throws if the result is not a valid DXN. Use tryMake for non-throwing string parsing.

    Static NSID strings are validated at compile time via

    Name

    : the final segment must be camelCase (no hyphens). Template-literal strings with a runtime prefix are accepted here but still validated at runtime.

    @example make('org.dxos.type.calendar') → 'dxn:org.dxos.type.calendar'

    @example make('org.dxos.type.calendar', '1.0.0') → 'dxn:org.dxos.type.calendar:1.0.0'

    make
    ('com.example.type.organization', '0.1.0'))(
    import Schema
    Schema
    .
    function Struct<{
    readonly name: Schema.String;
    readonly website: Schema.optional<Schema.String>;
    }>(fields: {
    readonly name: Schema.String;
    readonly website: Schema.optional<Schema.String>;
    }): Schema.Struct<{
    readonly name: Schema.String;
    readonly website: Schema.optional<Schema.String>;
    }>

    Defines a struct schema from a map of field schemas.

    Details

    Each field value is a schema. Use

    optionalKey

    or

    optional

    to mark fields as optional, and

    mutableKey

    to mark them as mutable.

    The resulting schema's Type is a readonly object type with the fields' decoded types. The Encoded form mirrors the field schemas' encoded types. Declared fields may be inherited and are copied to own properties in the output. The __proto__ field is accepted only when it is an own property. Parsing does not guarantee that output keys retain their input order.

    Example (Defining a basic struct)

    import { Schema } from "effect"
    const Person = Schema.Struct({
    name: Schema.String,
    age: Schema.Number,
    email: Schema.optionalKey(Schema.String)
    })
    // { readonly name: string; readonly age: number; readonly email?: string }
    type Person = typeof Person.Type
    Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }

    @stability ― stable

    @category ― constructors

    @since ― 3.10.0

    Struct
    ({
    name: Schema.String
    name
    :
    import Schema
    Schema
    .
    const String: Schema.String

    Type-level representation of

    String

    .

    Schema for string values. Validates that the input is typeof "string".

    @stability ― stable

    @category ― models

    @since ― 4.0.0

    @stability ― stable

    @category ― schemas

    @since ― 4.0.0

    String
    ,
    website: Schema.optional<Schema.String>
    website
    :
    import Schema
    Schema
    .
    const optional: optionalLambda
    <Schema.String>(self: Schema.String) => Schema.optional<Schema.String>

    Type-level representation returned by

    optional

    .

    Marks a struct field as optional, allowing the key to be absent or undefined.

    Details

    The resulting property may be absent or explicitly set to undefined. Equivalent to optionalKey(UndefinedOr(S)).

    Use

    optionalKey

    instead if you want exact optional semantics (absent only, not undefined).

    Example (Defining an optional field accepting undefined)

    import { Schema } from "effect"
    const schema = Schema.Struct({
    name: Schema.String,
    age: Schema.optional(Schema.Number)
    })
    // { readonly name: string; readonly age?: number | undefined }
    type Person = typeof schema.Type

    @stability ― stable

    @category ― models

    @since ― 3.10.0

    @stability ― stable

    @category ― combinators

    @since ― 3.10.0

    optional
    (
    import Format
    Format
    .URL),
    }).
    Pipeable.pipe<Schema.Struct<{
    readonly name: Schema.String;
    readonly website: Schema.optional<Schema.String>;
    }>, Schema.Struct<{
    readonly name: Schema.String;
    readonly website: Schema.optional<Schema.String>;
    }>>(this: Schema.Struct<...>, ab: (_: Schema.Struct<{
    readonly name: Schema.String;
    readonly website: Schema.optional<Schema.String>;
    }>) => Schema.Struct<{
    readonly name: Schema.String;
    readonly website: Schema.optional<Schema.String>;
    }>): Schema.Struct<...> (+21 overloads)
    pipe
    (
    import Annotation
    Annotation
    .
    const IconAnnotation: Annotation.Annotation<Annotation.IconAnnotation>
    export IconAnnotation

    Icon to render in the UI.

    IconAnnotation
    .
    Annotation<IconAnnotation>.set: (value: Annotation.IconAnnotation) => <S extends Schema.Top>(schema: S) => S

    Set the annotation on an Effect schema.

    Only accepts Schema.Top — annotations must be applied to the source schema BEFORE wrapping it with Type.makeObject / Type.makeRelation. In a pipe, place every Annotation.X.set(...) before the Type.make... step.

    @performance ― O(value size) encode, once at schema-definition time.

    set
    ({
    icon: string

    Sprite icon name (e.g., 'ph--user--regular', 'ph--cube--regular', 'px--anthropic--regular').

    ph--* is Phosphor; px--* and dx--* are brand glyphs, which are sprite-only and carry no weight variants. All three are admitted because a type whose subject IS a brand — an Anthropic session, a GitHub repo — has no honest Phosphor equivalent.

    icon
    : 'ph--buildings--regular',
    hue?: string | undefined

    Color name.

    List of colors:

    • 'red'
    • 'orange'
    • 'amber'
    • 'yellow'
    • 'lime'
    • 'green'
    • 'emerald'
    • 'teal'
    • 'cyan'
    • 'violet'
    • 'purple'
    • 'fuchsia'
    • 'pink'
    • 'rose'

    hue
    : 'amber' })),
    ) {}

    Format.URL marks the website as a URL, so a form offers a URL field for it. IconAnnotation gives the type an icon and a hue, which the app’s list and graph use.

  2. Point a person at an organization. employer is a reference to an Organization.

    export class
    class Person
    Person
    extends
    import Type
    Type
    .
    const makeObject: <Person>(dxn: DXN.DXN, options?: {
    id?: EntityId;
    }) => Type.MakeObject<Person>

    Factory function to create an ECHO object type.

    Returns a Type.Type entity — a live, in-memory TypeSchema instance, NOT a Schema.Schema. Use Type.InstanceType<typeof Foo> for the instance type and Type.getSchema(Foo) to obtain the underlying Effect Schema.

    The entity's id defaults to EntityId.deterministic(typename, version) so constructing a type never reaches crypto.getRandomValues() — required for Cloudflare workerd, which forbids RNG calls in global (module-evaluation) scope. Pass { id } to override (e.g. with EntityId.random() from a request handler).

    Giving the type a nominal class name keeps its inferred type portable for declaration emit: structural expansion (which can pull in unnameable union members from referenced schemas) is replaced by a reference to the class.

    The second call takes either a schema, or struct fields (wrapped in Schema.Struct) with an optional function that pipes annotations onto the struct.

    @example

    export class Person extends Type.makeObject<Person>(DXN.make('com.example.type.myType', '0.1.0'))(Schema.Struct({
    name: Schema.String,
    })) {}
    export class Tag extends Type.makeObject<Tag>(DXN.make('com.example.type.tag', '0.1.0'))(
    { label: Schema.String },
    Annotation.LabelAnnotation.set(['label']),
    ) {}

    @performance ― O(schema size) once at definition time; builds the type entity eagerly, so call it at module scope, not per use.

    makeObject
    <
    class Person
    Person
    >(
    import DXN
    DXN
    .
    const make: <"com.example.type.person">(nsid: "com.example.type.person", version?: string) => DXN.DXN

    Constructs a DXN from an NSID (and optional version). Throws if the result is not a valid DXN. Use tryMake for non-throwing string parsing.

    Static NSID strings are validated at compile time via

    Name

    : the final segment must be camelCase (no hyphens). Template-literal strings with a runtime prefix are accepted here but still validated at runtime.

    @example make('org.dxos.type.calendar') → 'dxn:org.dxos.type.calendar'

    @example make('org.dxos.type.calendar', '1.0.0') → 'dxn:org.dxos.type.calendar:1.0.0'

    make
    ('com.example.type.person', '0.1.0'))(
    import Schema
    Schema
    .
    function Struct<{
    readonly name: Schema.String;
    readonly email: Schema.optional<Schema.String>;
    readonly employer: Schema.optional<Ref.RefSchema<Organization & OfKind<EntityKind.Object> & Unknown>>;
    }>(fields: {
    readonly name: Schema.String;
    readonly email: Schema.optional<Schema.String>;
    readonly employer: Schema.optional<Ref.RefSchema<Organization & OfKind<EntityKind.Object> & Unknown>>;
    }): Schema.Struct<...>

    Defines a struct schema from a map of field schemas.

    Details

    Each field value is a schema. Use

    optionalKey

    or

    optional

    to mark fields as optional, and

    mutableKey

    to mark them as mutable.

    The resulting schema's Type is a readonly object type with the fields' decoded types. The Encoded form mirrors the field schemas' encoded types. Declared fields may be inherited and are copied to own properties in the output. The __proto__ field is accepted only when it is an own property. Parsing does not guarantee that output keys retain their input order.

    Example (Defining a basic struct)

    import { Schema } from "effect"
    const Person = Schema.Struct({
    name: Schema.String,
    age: Schema.Number,
    email: Schema.optionalKey(Schema.String)
    })
    // { readonly name: string; readonly age: number; readonly email?: string }
    type Person = typeof Person.Type
    Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }

    @stability ― stable

    @category ― constructors

    @since ― 3.10.0

    Struct
    ({
    name: Schema.String
    name
    :
    import Schema
    Schema
    .
    const String: Schema.String

    Type-level representation of

    String

    .

    Schema for string values. Validates that the input is typeof "string".

    @stability ― stable

    @category ― models

    @since ― 4.0.0

    @stability ― stable

    @category ― schemas

    @since ― 4.0.0

    String
    ,
    email: Schema.optional<Schema.String>
    email
    :
    import Schema
    Schema
    .
    const optional: optionalLambda
    <Schema.String>(self: Schema.String) => Schema.optional<Schema.String>

    Type-level representation returned by

    optional

    .

    Marks a struct field as optional, allowing the key to be absent or undefined.

    Details

    The resulting property may be absent or explicitly set to undefined. Equivalent to optionalKey(UndefinedOr(S)).

    Use

    optionalKey

    instead if you want exact optional semantics (absent only, not undefined).

    Example (Defining an optional field accepting undefined)

    import { Schema } from "effect"
    const schema = Schema.Struct({
    name: Schema.String,
    age: Schema.optional(Schema.Number)
    })
    // { readonly name: string; readonly age?: number | undefined }
    type Person = typeof schema.Type

    @stability ― stable

    @category ― models

    @since ― 3.10.0

    @stability ― stable

    @category ― combinators

    @since ― 3.10.0

    optional
    (
    import Format
    Format
    .
    const Email: Schema.String

    Email address (RFC 5321). The local part also allows an apostrophe, which real mail carries (o'day@corp.com). https://datatracker.ietf.org/doc/html/rfc5321#section-4.1.2

    Email
    ),
    employer: Schema.optional<Ref.RefSchema<Organization & OfKind<EntityKind.Object> & Unknown>>
    employer
    :
    import Schema
    Schema
    .
    const optional: optionalLambda
    <Ref.RefSchema<Organization & OfKind<EntityKind.Object> & Unknown>>(self: Ref.RefSchema<Organization & OfKind<EntityKind.Object> & Unknown>) => Schema.optional<Ref.RefSchema<Organization & OfKind<EntityKind.Object> & Unknown>>

    Type-level representation returned by

    optional

    .

    Marks a struct field as optional, allowing the key to be absent or undefined.

    Details

    The resulting property may be absent or explicitly set to undefined. Equivalent to optionalKey(UndefinedOr(S)).

    Use

    optionalKey

    instead if you want exact optional semantics (absent only, not undefined).

    Example (Defining an optional field accepting undefined)

    import { Schema } from "effect"
    const schema = Schema.Struct({
    name: Schema.String,
    age: Schema.optional(Schema.Number)
    })
    // { readonly name: string; readonly age?: number | undefined }
    type Person = typeof schema.Type

    @stability ― stable

    @category ― models

    @since ― 3.10.0

    @stability ― stable

    @category ― combinators

    @since ― 3.10.0

    optional
    (
    import Ref
    Ref
    .
    const Ref: <typeof Organization>(type: typeof Organization) => Ref.RefSchema<Organization & OfKind<EntityKind.Object> & Unknown> (+3 overloads)
    Ref
    (
    class Organization
    Organization
    )),
    }).
    Pipeable.pipe<Schema.Struct<{
    readonly name: Schema.String;
    readonly email: Schema.optional<Schema.String>;
    readonly employer: Schema.optional<Ref.RefSchema<Organization & OfKind<EntityKind.Object> & Unknown>>;
    }>, Schema.Struct<{
    readonly name: Schema.String;
    readonly email: Schema.optional<Schema.String>;
    readonly employer: Schema.optional<Ref.RefSchema<Organization & OfKind<EntityKind.Object> & Unknown>>;
    }>>(this: Schema.Struct<...>, ab: (_: Schema.Struct<...>) => Schema.Struct<...>): Schema.Struct<...> (+21 overloads)
    pipe
    (
    import Annotation
    Annotation
    .
    const IconAnnotation: Annotation.Annotation<Annotation.IconAnnotation>
    export IconAnnotation

    Icon to render in the UI.

    IconAnnotation
    .
    Annotation<IconAnnotation>.set: (value: Annotation.IconAnnotation) => <S extends Schema.Top>(schema: S) => S

    Set the annotation on an Effect schema.

    Only accepts Schema.Top — annotations must be applied to the source schema BEFORE wrapping it with Type.makeObject / Type.makeRelation. In a pipe, place every Annotation.X.set(...) before the Type.make... step.

    @performance ― O(value size) encode, once at schema-definition time.

    set
    ({
    icon: string

    Sprite icon name (e.g., 'ph--user--regular', 'ph--cube--regular', 'px--anthropic--regular').

    ph--* is Phosphor; px--* and dx--* are brand glyphs, which are sprite-only and carry no weight variants. All three are admitted because a type whose subject IS a brand — an Anthropic session, a GitHub repo — has no honest Phosphor equivalent.

    icon
    : 'ph--user--regular',
    hue?: string | undefined

    Color name.

    List of colors:

    • 'red'
    • 'orange'
    • 'amber'
    • 'yellow'
    • 'lime'
    • 'green'
    • 'emerald'
    • 'teal'
    • 'cyan'
    • 'violet'
    • 'purple'
    • 'fuchsia'
    • 'pink'
    • 'rose'

    hue
    : 'cyan' })),
    ) {}
  3. Point an event at many people. A list of references gives an event its attendees. LabelAnnotation says which field names an event, since it has a title rather than a name.

    export class
    class Event
    Event
    extends
    import Type
    Type
    .
    const makeObject: <Event>(dxn: DXN.DXN, options?: {
    id?: EntityId;
    }) => Type.MakeObject<Event>

    Factory function to create an ECHO object type.

    Returns a Type.Type entity — a live, in-memory TypeSchema instance, NOT a Schema.Schema. Use Type.InstanceType<typeof Foo> for the instance type and Type.getSchema(Foo) to obtain the underlying Effect Schema.

    The entity's id defaults to EntityId.deterministic(typename, version) so constructing a type never reaches crypto.getRandomValues() — required for Cloudflare workerd, which forbids RNG calls in global (module-evaluation) scope. Pass { id } to override (e.g. with EntityId.random() from a request handler).

    Giving the type a nominal class name keeps its inferred type portable for declaration emit: structural expansion (which can pull in unnameable union members from referenced schemas) is replaced by a reference to the class.

    The second call takes either a schema, or struct fields (wrapped in Schema.Struct) with an optional function that pipes annotations onto the struct.

    @example

    export class Person extends Type.makeObject<Person>(DXN.make('com.example.type.myType', '0.1.0'))(Schema.Struct({
    name: Schema.String,
    })) {}
    export class Tag extends Type.makeObject<Tag>(DXN.make('com.example.type.tag', '0.1.0'))(
    { label: Schema.String },
    Annotation.LabelAnnotation.set(['label']),
    ) {}

    @performance ― O(schema size) once at definition time; builds the type entity eagerly, so call it at module scope, not per use.

    makeObject
    <
    class Event
    Event
    >(
    import DXN
    DXN
    .
    const make: <"com.example.type.event">(nsid: "com.example.type.event", version?: string) => DXN.DXN

    Constructs a DXN from an NSID (and optional version). Throws if the result is not a valid DXN. Use tryMake for non-throwing string parsing.

    Static NSID strings are validated at compile time via

    Name

    : the final segment must be camelCase (no hyphens). Template-literal strings with a runtime prefix are accepted here but still validated at runtime.

    @example make('org.dxos.type.calendar') → 'dxn:org.dxos.type.calendar'

    @example make('org.dxos.type.calendar', '1.0.0') → 'dxn:org.dxos.type.calendar:1.0.0'

    make
    ('com.example.type.event', '0.1.0'))(
    import Schema
    Schema
    .
    function Struct<{
    readonly title: Schema.String;
    readonly description: Schema.optional<Schema.String>;
    readonly attendees: Schema.optional<Schema.$Array<Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown>>>;
    }>(fields: {
    readonly title: Schema.String;
    readonly description: Schema.optional<Schema.String>;
    readonly attendees: Schema.optional<Schema.$Array<Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown>>>;
    }): Schema.Struct<...>

    Defines a struct schema from a map of field schemas.

    Details

    Each field value is a schema. Use

    optionalKey

    or

    optional

    to mark fields as optional, and

    mutableKey

    to mark them as mutable.

    The resulting schema's Type is a readonly object type with the fields' decoded types. The Encoded form mirrors the field schemas' encoded types. Declared fields may be inherited and are copied to own properties in the output. The __proto__ field is accepted only when it is an own property. Parsing does not guarantee that output keys retain their input order.

    Example (Defining a basic struct)

    import { Schema } from "effect"
    const Person = Schema.Struct({
    name: Schema.String,
    age: Schema.Number,
    email: Schema.optionalKey(Schema.String)
    })
    // { readonly name: string; readonly age: number; readonly email?: string }
    type Person = typeof Person.Type
    Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }

    @stability ― stable

    @category ― constructors

    @since ― 3.10.0

    Struct
    ({
    title: Schema.String
    title
    :
    import Schema
    Schema
    .
    const String: Schema.String

    Type-level representation of

    String

    .

    Schema for string values. Validates that the input is typeof "string".

    @stability ― stable

    @category ― models

    @since ― 4.0.0

    @stability ― stable

    @category ― schemas

    @since ― 4.0.0

    String
    ,
    description: Schema.optional<Schema.String>
    description
    :
    import Schema
    Schema
    .
    const optional: optionalLambda
    <Schema.String>(self: Schema.String) => Schema.optional<Schema.String>

    Type-level representation returned by

    optional

    .

    Marks a struct field as optional, allowing the key to be absent or undefined.

    Details

    The resulting property may be absent or explicitly set to undefined. Equivalent to optionalKey(UndefinedOr(S)).

    Use

    optionalKey

    instead if you want exact optional semantics (absent only, not undefined).

    Example (Defining an optional field accepting undefined)

    import { Schema } from "effect"
    const schema = Schema.Struct({
    name: Schema.String,
    age: Schema.optional(Schema.Number)
    })
    // { readonly name: string; readonly age?: number | undefined }
    type Person = typeof schema.Type

    @stability ― stable

    @category ― models

    @since ― 3.10.0

    @stability ― stable

    @category ― combinators

    @since ― 3.10.0

    optional
    (
    import Schema
    Schema
    .
    const String: Schema.String

    Type-level representation of

    String

    .

    Schema for string values. Validates that the input is typeof "string".

    @stability ― stable

    @category ― models

    @since ― 4.0.0

    @stability ― stable

    @category ― schemas

    @since ― 4.0.0

    String
    ),
    attendees: Schema.optional<Schema.$Array<Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown>>>
    attendees
    :
    import Schema
    Schema
    .
    const optional: optionalLambda
    <Schema.$Array<Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown>>>(self: Schema.$Array<Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown>>) => Schema.optional<Schema.$Array<Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown>>>

    Type-level representation returned by

    optional

    .

    Marks a struct field as optional, allowing the key to be absent or undefined.

    Details

    The resulting property may be absent or explicitly set to undefined. Equivalent to optionalKey(UndefinedOr(S)).

    Use

    optionalKey

    instead if you want exact optional semantics (absent only, not undefined).

    Example (Defining an optional field accepting undefined)

    import { Schema } from "effect"
    const schema = Schema.Struct({
    name: Schema.String,
    age: Schema.optional(Schema.Number)
    })
    // { readonly name: string; readonly age?: number | undefined }
    type Person = typeof schema.Type

    @stability ― stable

    @category ― models

    @since ― 3.10.0

    @stability ― stable

    @category ― combinators

    @since ― 3.10.0

    optional
    (
    import Schema
    Schema
    .
    Array<Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown>>(self: Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown>): Schema.$Array<Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown>>
    export Array

    Defines a ReadonlyArray schema for a given element schema.

    Example (Defining an array of strings)

    import { Schema } from "effect"
    const schema = Schema.Array(Schema.String)
    Schema.decodeUnknownSync(schema)(["a", "b", "c"]) // => ["a", "b", "c"]

    @stability ― stable

    @category ― constructors

    @since ― 4.0.0

    Array
    (
    import Ref
    Ref
    .
    const Ref: <typeof Person>(type: typeof Person) => Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown> (+3 overloads)
    Ref
    (
    class Person
    Person
    ))),
    }).
    Pipeable.pipe<Schema.Struct<{
    readonly title: Schema.String;
    readonly description: Schema.optional<Schema.String>;
    readonly attendees: Schema.optional<Schema.$Array<Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown>>>;
    }>, Schema.Struct<{
    readonly title: Schema.String;
    readonly description: Schema.optional<Schema.String>;
    readonly attendees: Schema.optional<Schema.$Array<Ref.RefSchema<Person & OfKind<EntityKind.Object> & Unknown>>>;
    }>, Schema.Struct<...>>(this: Schema.Struct<...>, ab: (_: Schema.Struct<...>) => Schema.Struct<...>, bc: (_: Schema.Struct<...>) => Schema.Struct<...>): Schema.Struct<...> (+21 overloads)
    pipe
    (
    import Annotation
    Annotation
    .
    const IconAnnotation: Annotation.Annotation<Annotation.IconAnnotation>
    export IconAnnotation

    Icon to render in the UI.

    IconAnnotation
    .
    Annotation<IconAnnotation>.set: (value: Annotation.IconAnnotation) => <S extends Schema.Top>(schema: S) => S

    Set the annotation on an Effect schema.

    Only accepts Schema.Top — annotations must be applied to the source schema BEFORE wrapping it with Type.makeObject / Type.makeRelation. In a pipe, place every Annotation.X.set(...) before the Type.make... step.

    @performance ― O(value size) encode, once at schema-definition time.

    set
    ({
    icon: string

    Sprite icon name (e.g., 'ph--user--regular', 'ph--cube--regular', 'px--anthropic--regular').

    ph--* is Phosphor; px--* and dx--* are brand glyphs, which are sprite-only and carry no weight variants. All three are admitted because a type whose subject IS a brand — an Anthropic session, a GitHub repo — has no honest Phosphor equivalent.

    icon
    : 'ph--calendar-dots--regular',
    hue?: string | undefined

    Color name.

    List of colors:

    • 'red'
    • 'orange'
    • 'amber'
    • 'yellow'
    • 'lime'
    • 'green'
    • 'emerald'
    • 'teal'
    • 'cyan'
    • 'violet'
    • 'purple'
    • 'fuchsia'
    • 'pink'
    • 'rose'

    hue
    : 'green' }),
    import Annotation
    Annotation
    .
    const LabelAnnotation: AnnotationHelper<string[]>
    export LabelAnnotation
    LabelAnnotation
    .
    AnnotationHelper<string[]>.set: (value: string[]) => <S extends Schema.Top>(schema: S) => S

    Set the annotation on an Effect schema.

    Only accepts Schema.Top — annotations must be applied to the source schema BEFORE wrapping it with Type.makeObject / Type.makeRelation. In a pipe, place every Annotation.X.set(...) before the Type.make... step.

    set
    (['title']),
    ),
    ) {}
  4. List the types. The client is given this list when the app starts, in Installation.

    export const
    const types: (typeof Organization | typeof Person | typeof Event)[]
    types
    = [
    class Organization
    Organization
    ,
    class Person
    Person
    ,
    class Event
    Event
    ];
  5. Create instances. Obj.make takes the props the schema allows, and Ref.make makes a reference to an object.

    const
    const northwind: Obj.OfShape<Organization & OfKind<EntityKind.Object>>
    northwind
    =
    import Obj
    Obj
    .
    function make<typeof Organization>(type: typeof Organization, props: NoInfer<Obj.MakeProps<typeof Organization>>, options?: Obj.MakeOptions): Obj.OfShape<Organization & OfKind<EntityKind.Object>>

    Creates a new echo object of the given schema or Type.Type.

    @param ― typeOrSchema - A static object schema (Type.makeObject(...)) or a Type.Type entity (e.g. one returned by db.addType(schemaEntity)).

    @param ― props - Object properties.

    @param ―

    options - See MakeOptions.

    Meta can be passed as a symbol in props.

    Example:

    const obj = Obj.make(Person, { [Obj.Meta]: { keys: [...] }, name: 'John' });

    Note: Only accepts object schemas / object-kind types, not relation schemas. Use Relation.make for relations.

    @performance ― O(n) in props size; validates props against the schema and allocates a reactive proxy, with no database I/O.

    make
    (
    class Organization
    Organization
    , {
    name: string
    name
    : 'Northwind Labs',
    website?: string | undefined
    website
    : 'https://northwind.example' });
    const
    const ada: Obj.OfShape<Person & OfKind<EntityKind.Object>>
    ada
    =
    import Obj
    Obj
    .
    function make<typeof Person>(type: typeof Person, props: NoInfer<Obj.MakeProps<typeof Person>>, options?: Obj.MakeOptions): Obj.OfShape<Person & OfKind<EntityKind.Object>>

    Creates a new echo object of the given schema or Type.Type.

    @param ― typeOrSchema - A static object schema (Type.makeObject(...)) or a Type.Type entity (e.g. one returned by db.addType(schemaEntity)).

    @param ― props - Object properties.

    @param ―

    options - See MakeOptions.

    Meta can be passed as a symbol in props.

    Example:

    const obj = Obj.make(Person, { [Obj.Meta]: { keys: [...] }, name: 'John' });

    Note: Only accepts object schemas / object-kind types, not relation schemas. Use Relation.make for relations.

    @performance ― O(n) in props size; validates props against the schema and allocates a reactive proxy, with no database I/O.

    make
    (
    class Person
    Person
    , {
    name: string
    name
    : 'Ada Lovelace',
    employer?: Ref<Organization & OfKind<EntityKind.Object> & Obj.Unknown> | undefined
    employer
    :
    import Ref
    Ref
    .
    const make: <Obj.OfShape<Organization & OfKind<EntityKind.Object>>>(object: Obj.OfShape<Organization & OfKind<EntityKind.Object>>) => Ref<Obj.OfShape<Organization & OfKind<EntityKind.Object>>>

    Create a reference to an entity.

    @performance ― O(1); allocates a ref that inlines the target, with no lookup.

    make
    (
    const northwind: Obj.OfShape<Organization & OfKind<EntityKind.Object>>
    northwind
    ) });
    const
    const review: Obj.OfShape<Event & OfKind<EntityKind.Object>>
    review
    =
    import Obj
    Obj
    .
    function make<typeof Event>(type: typeof Event, props: NoInfer<Obj.MakeProps<typeof Event>>, options?: Obj.MakeOptions): Obj.OfShape<Event & OfKind<EntityKind.Object>>

    Creates a new echo object of the given schema or Type.Type.

    @param ― typeOrSchema - A static object schema (Type.makeObject(...)) or a Type.Type entity (e.g. one returned by db.addType(schemaEntity)).

    @param ― props - Object properties.

    @param ―

    options - See MakeOptions.

    Meta can be passed as a symbol in props.

    Example:

    const obj = Obj.make(Person, { [Obj.Meta]: { keys: [...] }, name: 'John' });

    Note: Only accepts object schemas / object-kind types, not relation schemas. Use Relation.make for relations.

    @performance ― O(n) in props size; validates props against the schema and allocates a reactive proxy, with no database I/O.

    make
    (
    class Event
    Event
    , {
    title: string
    title
    : 'Quarterly review',
    attendees?: readonly Ref<Person & OfKind<EntityKind.Object> & Obj.Unknown>[] | undefined
    attendees
    : [
    import Ref
    Ref
    .
    const make: <Obj.OfShape<Person & OfKind<EntityKind.Object>>>(object: Obj.OfShape<Person & OfKind<EntityKind.Object>>) => Ref<Obj.OfShape<Person & OfKind<EntityKind.Object>>>

    Create a reference to an entity.

    @performance ― O(1); allocates a ref that inlines the target, with no lookup.

    make
    (
    const ada: Obj.OfShape<Person & OfKind<EntityKind.Object>>
    ada
    )] });

    Leave out a person’s name and the compiler rejects the call.

  6. Follow a reference. peek reads the target, if it is loaded, without waiting.

    // The reference holds the organization's identity, not a copy of it.
    const
    const employer: (Organization & OfKind<EntityKind.Object> & Obj.Unknown) | undefined
    employer
    =
    const ada: Obj.OfShape<Person & OfKind<EntityKind.Object>>
    ada
    .
    employer?: Ref<Organization & OfKind<EntityKind.Object> & Obj.Unknown> | undefined
    employer
    ?.
    Ref<Organization & OfKind<EntityKind.Object> & Unknown>.peek(): (Organization & OfKind<EntityKind.Object> & Obj.Unknown) | undefined

    @returns ― The target when it is already materialized: the pinned target, or a side-effect-free working-set lookup. Never throws and never triggers loading — the synchronous counterpart of tryLoad . A just-added object can resolve here before it has settled into its own document; callers that need a settled document must load instead.

    @performance ― O(1) working-set lookup; never loads and never throws.

    peek
    ();
    var console: Console

    The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

    The module exports two specific components:

    • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
    • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

    Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

    Example using the global console:

    console.log('hello world');
    // Prints: hello world, to stdout
    console.log('hello %s', 'world');
    // Prints: hello world, to stdout
    console.error(new Error('Whoops, something bad happened'));
    // Prints error message and stack trace to stderr:
    // Error: Whoops, something bad happened
    // at [eval]:5:15
    // at Script.runInThisContext (node:vm:132:18)
    // at Object.runInThisContext (node:vm:309:38)
    // at node:internal/process/execution:77:19
    // at [eval]-wrapper:6:22
    // at evalScript (node:internal/process/execution:76:60)
    // at node:internal/main/eval_string:23:3
    const name = 'Will Robinson';
    console.warn(`Danger ${name}! Danger!`);
    // Prints: Danger Will Robinson! Danger!, to stderr

    Example using the Console class:

    const out = getStreamSomehow();
    const err = getStreamSomehow();
    const myConsole = new console.Console(out, err);
    myConsole.log('hello world');
    // Prints: hello world, to out
    myConsole.log('hello %s', 'world');
    // Prints: hello world, to out
    myConsole.error(new Error('Whoops, something bad happened'));
    // Prints: [Error: Whoops, something bad happened], to err
    const name = 'Will Robinson';
    myConsole.warn(`Danger ${name}! Danger!`);
    // Prints: Danger Will Robinson! Danger!, to err

    @see ― source

    console
    .
    Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)

    Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

    const count = 5;
    console.log('count: %d', count);
    // Prints: count: 5, to stdout
    console.log('count:', count);
    // Prints: count: 5, to stdout

    See util.format() for more information.

    @since ― v0.1.100

    log
    (
    const employer: (Organization & OfKind<EntityKind.Object> & Obj.Unknown) | undefined
    employer
    ?.
    name: string | undefined
    name
    );

The form beside the list is built from the selected type’s schema: a URL field for a website, a picker of organizations for an employer, and a list of people for an event’s attendees. Choose a type to see its form, or a record to see its values. Editing comes on the next page.

You can declare object types with references between them, give a type an icon and a label, and create objects that the compiler checks against their schema.

Mutating objects: add, change and remove the app’s records.