Skip to content

feat: accept io-ts codecs as table field types - #8

Merged
Upd4ting merged 2 commits into
mainfrom
feat/schema-iots-fields
May 21, 2026
Merged

feat: accept io-ts codecs as table field types#8
Upd4ting merged 2 commits into
mainfrom
feat/schema-iots-fields

Conversation

@Thomasims

@Thomasims Thomasims commented May 20, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Widen FieldType in src/schema.ts to accept any io-ts-shaped codec at the root of a field, alongside the existing string-token vocabulary. Codecs do not nest inside string-tree records — use io-ts combinators (t.type, t.array, …) for nesting within a codec.
  • The codec arm is expressed as a local structural interface (_A/_O/_I/name/is/encode/decode) so the emitted .d.ts is self-contained; consumers don't need io-ts resolvable to use FieldType.
  • Export StringFieldType alongside FieldType for consumers that want to spell the string-only arm.
  • Update docs/3.results/4.table_changes.md with the codec arm and a short example.
  • Add src/tests/datasets/codec_fields.ts as a compile-time check that codec-flavored schemas type-check.

The interface remains a thin pass-through — no runtime validation is added here; codecs flow through Schemas.register to adapters.

Test plan

  • pnpm install succeeds
  • pnpm run build succeeds and dist/schema.d.ts has no import("io-ts") reference
  • pnpm run lint is clean
  • Existing string-token datasets (src/tests/datasets/users.ts, products.ts) still type-check unchanged (non-breaking)
  • New src/tests/datasets/codec_fields.ts type-checks without as any or suppressions

Greptile Summary

This PR widens FieldType in src/schema.ts to accept io-ts codecs alongside the existing string-token vocabulary, using a self-contained local structural interface (IoTsCodec) so io-ts does not appear as an import in the emitted .d.ts. StringFieldType is now exported for consumers who need to reference the string-only arm explicitly.

  • src/schema.ts: Renames the original FieldType to StringFieldType (now exported), introduces a local IoTsCodec structural interface, and re-exports FieldType = StringFieldType | IoTsCodec — no io-ts import, keeping the emitted declaration self-contained.
  • src/tests/datasets/codec_fields.ts: New compile-time test confirming that io-ts codecs type-check correctly as field values inside a SchemaDefinition.
  • package.json / pnpm-lock.yaml: Adds fp-ts and io-ts as devDependencies so the new test dataset compiles in CI.

Confidence Score: 5/5

Safe to merge — the change is additive and non-breaking; existing string-token schemas are unaffected.

The structural IoTsCodec interface correctly avoids any io-ts import in the emitted declaration, the string-token path is unchanged, and the new compile-time test dataset validates the codec arm. The two findings are minor documentation and export surface observations that don't affect runtime correctness.

The documentation in docs/3.results/4.table_changes.md references import("io-ts").Mixed rather than the actual local structural type, which is worth correcting before the docs are published.

Important Files Changed

Filename Overview
src/schema.ts Introduces local structural IoTsCodec interface and StringFieldType alias; widens FieldType to accept codecs without importing from io-ts. IoTsCodec is not exported (minor).
docs/3.results/4.table_changes.md Documents the new codec arm as import("io-ts").Mixed which doesn't match the actual local structural interface in the emitted .d.ts.
src/tests/datasets/codec_fields.ts Compile-time test dataset validating that io-ts codecs type-check correctly against SchemaDefinition; looks correct.
package.json Adds fp-ts and io-ts as devDependencies so the compile-time test dataset builds correctly.

Class Diagram

%%{init: {'theme': 'neutral'}}%%
classDiagram
    class StringFieldType {
        <<type>>
        string
        Array~StringFieldType~
        Record~string, StringFieldType~
    }

    class IoTsCodec {
        <<interface>>
        +readonly _A: unknown
        +readonly _O: unknown
        +readonly _I: unknown
        +readonly name: string
        +is(u: unknown) boolean
        +encode(a: never) unknown
        +decode(i: unknown) unknown
    }

    class FieldType {
        <<type>>
        StringFieldType | IoTsCodec
    }

    class TableDefinition {
        <<interface>>
        +fields: Record~string, FieldType~
        +indexes: Record~string, IndexDefinition~
    }

    class SchemaDefinition {
        <<interface>>
        +[tableName: string]: TableDefinition
    }

    FieldType ..> StringFieldType : union arm
    FieldType ..> IoTsCodec : union arm
    TableDefinition --> FieldType : fields values
    SchemaDefinition --> TableDefinition : table values
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
docs/3.results/4.table_changes.md:22-25
**Documentation type doesn't match the actual implementation**

The rendered `FieldType` in the docs references `import("io-ts").Mixed`, but the real exported type uses a local structural interface `IoTsCodec` with no import from `io-ts`. This misrepresents the contract to consumers: readers of the docs may think `io-ts` is a required transitive dependency for the type to exist, while the actual design deliberately avoids that. The codec arm should be documented as the local structural shape (or simply as "an io-ts-compatible codec object") to stay consistent with what `dist/schema.d.ts` will actually contain.

### Issue 2 of 2
src/schema.ts:26
`IoTsCodec` is the codec arm of the public `FieldType` union, but it is not exported. Consumers who want to write a helper or type guard that specifically accepts only the codec branch — not the full `FieldType` — have no way to reference it. `StringFieldType` was correctly exported for the same reason; exporting `IoTsCodec` keeps the public API surface symmetric.

```suggestion
export interface IoTsCodec {
```

Reviews (2): Last reviewed commit: "address greptile review feedback (greplo..." | Re-trigger Greptile

Widen FieldType to also accept any io-ts Mixed codec at the root of a
field, alongside the existing string-token vocabulary. Codecs don't
nest inside string-tree records; use io-ts combinators for nesting
inside a codec. io-ts is declared as an optional peer dependency.
Comment thread src/schema.ts Outdated
Comment thread package.json Outdated
Comment thread src/schema.ts Outdated
@Thomasims

Copy link
Copy Markdown
Contributor Author

@greptile review

@Upd4ting
Upd4ting merged commit 8382ea0 into main May 21, 2026
3 checks passed
@Upd4ting
Upd4ting deleted the feat/schema-iots-fields branch May 21, 2026 13:37
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