Skip to content

fix(codegen-ts): emit JS array literal for isArray @default (TS2345)#146

Merged
dmealing merged 1 commit into
mainfrom
fix/codegen-ts-array-default
Jul 2, 2026
Merged

fix(codegen-ts): emit JS array literal for isArray @default (TS2345)#146
dmealing merged 1 commit into
mainfrom
fix/codegen-ts-array-default

Conversation

@dmealing

@dmealing dmealing commented Jul 2, 2026

Copy link
Copy Markdown
Member

Problem

A downstream adopter upgrading to 0.15.1 hit non-compiling Drizzle output for an array field with a default. For field.string { name: conditions, isArray: true, default: "{}" } the pg entity generator emitted:

conditions: text("conditions").array().notNull().default("{}")

which fails tsc with TS2345 — Drizzle's .array().default(x) wants string[] | SQL<unknown>, not a string. The same shape broke SQLite (.$type<E[]>().default("{}")).

Why it regressed at 0.15.0

Before 0.15.0 an isArray string field mapped to jsonb, where .default("[]") was valid. The 0.15.0 @dbColumnType slim-and-derive (ADR-0036) made isArray emit a native text[] (.array()) column, but the default-emitter still passed the raw @default string through. Scalar/flat defaults were unaffected.

Why it can't be fixed in metadata

The Java loader requires @default to be a string (default: [] fails load), so an array default MUST be authored as a string ("[]" / "{}"). The fix belongs in codegen-ts.

Fix

Parse the metadata default string for a scalar isArray field into a real JS array literal, via a new { kind: "arrayLiteral", elements } DefaultExpr:

  • "{}" / "[]".default([])
  • "{a,b}" / '["a","b"]'.default(["a", "b"]) (elements quoted per element type — strings quoted, numerics bare)
  • ambiguous/unsupported shape → .default(sql\...`)` raw-SQL fallback so the output always typechecks, never a bare string

Scalar/flat defaults and object/map-array storage are byte-identical. Emission is dialect-agnostic (works for pg .array() and sqlite json .$type<E[]>()).

Tests

  • column-mapper.test.ts — shape assertions for {}/[]/{a,b}/JSON-array/int-array/fallback/scalar-unchanged.
  • array-default-compile.test.ts (new) — a real-tsc compile guard (mirrors test/projection/compile.test.ts) that generates the entity and asserts ZERO TS diagnostics on both dialects. Confirmed it reproduces the exact TS2345 without the fix and passes with it.

Verification

  • bun test packages/codegen-ts → 987 pass / 0 fail
  • bun run --filter '*' typecheck → clean (whole workspace)

Cross-port note

Java currently ignores array @default (emits none) — this fix is TS-specific, so the fixture is kept TS-local (not added to the shared codegen-conformance corpus). Java array-defaults are a possible follow-up.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GF9xLEQZaPus5Y6opk398n

A downstream adopter upgrading to 0.15.1 hit non-compiling Drizzle output for
an array field with a default, e.g. `field.string { isArray: true,
default: "{}" }`. The pg entity generator emitted
`text("conditions").array().notNull().default("{}")`, which fails `tsc` with
TS2345 — Drizzle's `.array().default(x)` wants `string[] | SQL`, not a string.
The same shape broke SQLite (`.$type<E[]>().default("{}")`).

Root cause: pre-0.15.0 an isArray string field mapped to jsonb, where
`.default("[]")` was valid. The 0.15.0 @dbColumnType slim-and-derive (ADR-0036)
made isArray emit a native text[] (`.array()`) column, but the default-emitter
still passed the raw @default string through.

Fix (codegen-ts only — the Java loader requires @default to be a string, so an
array default MUST be authored as "[]"/"{}"; it cannot be fixed in metadata):
parse the metadata default string for a scalar isArray field into a real JS
array literal via a new `{ kind: "arrayLiteral", elements }` DefaultExpr.
  - "{}" / "[]"       -> .default([])
  - "{a,b}" / '["a","b"]' -> .default(["a", "b"]) (elements quoted per type)
  - unsupported/ambiguous shape -> .default(sql`...`) so output ALWAYS
    typechecks, never a bare string
Scalar/flat defaults and object/map-array storage are byte-identical.

Tests: shape assertions in column-mapper.test.ts plus a real-tsc compile guard
(array-default-compile.test.ts, mirroring projection/compile.test.ts) that
proves the generated entity typechecks with ZERO diagnostics on both dialects —
it reproduces the exact TS2345 without the fix.

Cross-port note: Java currently ignores array @default (emits none); this fix
is TS-specific, so the fixture is kept TS-local (not in the shared
codegen-conformance corpus).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GF9xLEQZaPus5Y6opk398n
@dmealing
dmealing merged commit 8626fc9 into main Jul 2, 2026
1 check passed
@dmealing
dmealing deleted the fix/codegen-ts-array-default branch July 2, 2026 11:18
dmealing pushed a commit that referenced this pull request Jul 2, 2026
npm lockstep to 0.15.2 — codegen-ts isArray @default fix (#146) + cross-language
version-drift agent-context guidance (#147). Completes the coordinated patch
(Maven 7.7.2 / PyPI 0.15.3 / NuGet 0.15.2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GF9xLEQZaPus5Y6opk398n
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