clockworklabs / clockworklabs/SpacetimeDB

TypeScript: Type error when using .eq(...) on enum columns

Open
#4,506 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
25.2k
Forks
1.1k
Avg merge
2d 7h
Merged PRs (30d)
46

Description

Short

I tried making a view in SpacetimeDB server side with TypeScript that returns all rows that have enum value "Lamp".
The issue I am having makes the TypeScript type checker error when using the .eq(...) function when trying to filter based on the enum type.

Code in question

The following snippet is part of my project and raises a type error on the label.label.eq({ tag: "Lamp" }) statement.

// Schema definition for context
tretakt_special_labels: table(
    { public: false },
    {
      tretakt_switch_id: t.string().unique().primaryKey(),
      label: t.enum("Label", ["Lamp", "Switch"])
    }
  )

// View that raises issue
db_schema.anonymousView({ name: "binary_lamps", public: true },
  t.array(binary_lamps),
  (ctx) => {
    return ctx.from.tretakt_special_labels
      .where(label => label.label.eq({ tag: "Lamp" }))
      .rightSemijoinSemijoin(ctx.from.tretakt_switch, ((label, sw) => sw.id.eq(label.tretakt_switch_id)))
  }
)

Faulty behavior in detail

The .eq(...) function expects a value of type:

LiteralValue & RowType<TableDef>[ColumnName]

Where:

  • LiteralValue is a union of primitive types:
type LiteralValue =
  | string
  | number
  | bigint
  | boolean
  | Identity
  | Timestamp
  | ConnectionId;
  • RowType<TableDef>[ColumnName] for the label enum column is an object of shape:
{ tag: "Lamp" | "Switch" }

The intersection LiteralValue & { tag: "Lamp" | "Switch" } requires the value to be both a primitive and an object, which is impossible.
As a result, the type checker produces errors like:

Type '{ tag: "Lamp"; }' is not assignable to type 'Timestamp & { tag: "Lamp" | "Switch"; }'

This is a typing issue rather than a runtime problem: the ORM defines enum columns as objects ({ tag: EnumValue }), but .eq is typed to accept only rimitive literals. TypeScript therefore sees a type mismatch and rejects { tag: "Lamp" }.

Full typing error

No overload matches this call.
  Overload 1 of 2, '(literal: LiteralValue & { tag: "Lamp" | "Switch"; }): BooleanExpr<TableToSchema<"tretakt_special_labels", TableSchema<CoerceRow<{ tretakt_switch_id: StringColumnBuilder<{ isUnique: true; isPrimaryKey: true; }>; label: SimpleSumBuilderImpl<...>; }>, []>>>', gave the following error.
    Argument of type '{ tag: "Lamp"; }' is not assignable to parameter of type 'LiteralValue & { tag: "Lamp" | "Switch"; }'.
      Type '{ tag: "Lamp"; }' is not assignable to type 'Timestamp & { tag: "Lamp" | "Switch"; }'.
        Type '{ tag: "Lamp"; }' is missing the following properties from type 'Timestamp': __timestamp_micros_since_unix_epoch__, microsSinceUnixEpoch, toMillis, toDate, and 2 more.
  Overload 2 of 2, '(value: never): BooleanExpr<any>', gave the following error.
    Argument of type '{ tag: string; }' is not assignable to parameter of type 'never'.ts(2769)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the TypeScript definitions for enum columns, LiteralValue, RowType, and the .eq(...) overload described in the issue. Reproduce the error with the provided schema and view, then verify that comparing an enum value such as { tag: "Lamp" } type-checks correctly and is covered by a regression test.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.