Skip to content

Reorganize types generated for typescript clients#4127

Merged
jsdt merged 19 commits into2.0-breaking-changesfrom
jsdt/ts-type-gen
Feb 7, 2026
Merged

Reorganize types generated for typescript clients#4127
jsdt merged 19 commits into2.0-breaking-changesfrom
jsdt/ts-type-gen

Conversation

@jsdt
Copy link
Contributor

@jsdt jsdt commented Jan 26, 2026

Description of Changes

This changes generated types in ts client bindings. We currently generate a few different types of types: reducer args, procedure args, rows, and user defined types. To avoid potential conflicts between these types (for example, if a user defined a type called FooRow, and also had a tabled named foo, we would end up with two types named FooRow), this puts each set of types in a different file and namespace. We also stopped exporting the xxxRow types, because there is always another type generated for those. We now have a types directory, which has an index.ts with user defined types, along with reducers.ts and procedures.ts for the types generated for reducer/procedure parameters.

import type * as Types from './module_bindings/types';

var currentMessages: Types.Message[] = [];

or

import { type Message } from './module_bindings/types';

var currentMessages: Message[] = [];

This has a couple other changes:

  • For procedure and reducer types, this adds a suffix of Args, since we may want types for the return values in the future.
  • For all of the types, instead of exposing the schema object, we are now giving the typescript type (e.g. export type Message = __Infer<typeof MessageRow>;). I couldn't think of a reason for users to want the schema object, so this should save users from needing to do all of the Infer boilerplate.

API and ABI breaking changes

This is a breaking change for v2.

Expected complexity level and risk

  1. This only changes typescript, and it should generally make thing easier to use.

Testing

@jsdt jsdt changed the base branch from master to 2.0-breaking-changes January 26, 2026 19:55
@cloutiertyler
Copy link
Contributor

cloutiertyler commented Jan 29, 2026

For all of the types, instead of exposing the schema object, we are now giving the typescript type (e.g. export type Message = __Infer;). I couldn't think of a reason for users to want the schema object, so this should save users from needing to do all of the Infer boilerplate.

The reason is that there are helper functions on the schema object. For example:

private create<K extends keyof Variants & string>(

// So you can do stuff like:
MyEnum.create('foo');
MyEnum.create('bar', 32);

// instead of
{ tag: 'foo' }
{ tag: 'bar', value: 32 }

As one example. Or get the AlgebraicType as another example:

MyStruct.algebraicType

Which I know at least we need because we use it internally. Actually I'm curious to know how this compiles given that we use our own code gen internally.

@cloutiertyler
Copy link
Contributor

import { Rows } from './module_bindings';
var currentMessages: Rows.Message[] = [];

Won't this also conflict with a table called rows?

@cloutiertyler
Copy link
Contributor

For procedure and reducer types, this adds a suffix of Args, since we may want types for the return values in the future.

This is a much needed change 🙏.

@jsdt jsdt requested review from bfops and jdetter as code owners January 30, 2026 18:46
Copy link
Contributor

@cloutiertyler cloutiertyler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Heads up that args might be lying around still in various places other than the codegen.

@jsdt jsdt merged commit 3fb65b6 into 2.0-breaking-changes Feb 7, 2026
25 of 28 checks passed
joshua-spacetime pushed a commit that referenced this pull request Feb 10, 2026
This changes generated types in ts client bindings. We currently
generate a few different types of types: reducer args, procedure args,
rows, and user defined types. To avoid potential conflicts between these
types (for example, if a user defined a type called `FooRow`, and also
had a tabled named `foo`, we would end up with two types named
`FooRow`), this puts each set of types in a different file and
namespace. We also stopped exporting the `xxxRow` types, because there
is always another type generated for those. We now have a `types`
directory, which has an `index.ts` with user defined types, along with
`reducers.ts` and `procedures.ts` for the types generated for
reducer/procedure parameters.

```
import type * as Types from './module_bindings/types';

var currentMessages: Types.Message[] = [];
```

or

```
import { type Message } from './module_bindings/types';

var currentMessages: Message[] = [];
```

This has a couple other changes:
- For procedure and reducer types, this adds a suffix of `Args`, since
we may want types for the return values in the future.
- For all of the types, instead of exposing the schema object, we are
now giving the typescript type (e.g. `export type Message =
__Infer<typeof MessageRow>;`). I couldn't think of a reason for users to
want the schema object, so this should save users from needing to do all
of the `Infer` boilerplate.

This is a breaking change for v2.

2. This only changes typescript, and it should generally make thing
easier to use.

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [ ] <!-- maybe a test you want to do -->
- [ ] <!-- maybe a test you want a reviewer to do, so they can check it
off when they're satisfied. -->
pull bot pushed a commit to Spencerx/SpacetimeDB that referenced this pull request Feb 11, 2026
NOTE: Cherry-picking
clockworklabs#4127 from the
`2.0-breaking-changes` branch.

## Original PR Description

This changes generated types in ts client bindings. We currently
generate a few different types of types: reducer args, procedure args,
rows, and user defined types. To avoid potential conflicts between these
types (for example, if a user defined a type called `FooRow`, and also
had a tabled named `foo`, we would end up with two types named
`FooRow`), this puts each set of types in a different file and
namespace. We also stopped exporting the `xxxRow` types, because there
is always another type generated for those. We now have a `types`
directory, which has an `index.ts` with user defined types, along with
`reducers.ts` and `procedures.ts` for the types generated for
reducer/procedure parameters.

```
import type * as Types from './module_bindings/types';

var currentMessages: Types.Message[] = [];
```

or

```
import { type Message } from './module_bindings/types';

var currentMessages: Message[] = [];
```

This has a couple other changes:
- For procedure and reducer types, this adds a suffix of `Args`, since
we may want types for the return values in the future.
- For all of the types, instead of exposing the schema object, we are
now giving the typescript type (e.g. `export type Message =
__Infer<typeof MessageRow>;`). I couldn't think of a reason for users to
want the schema object, so this should save users from needing to do all
of the `Infer` boilerplate.

This is a breaking change for v2.

2. This only changes typescript, and it should generally make thing
easier to use.

---------

Co-authored-by: Jeffrey Dallatezza <jeffreydallatezza@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants