Skip to content

codegen-ts 0.24.0 emits enum types as value imports — TS1484 under verbatimModuleSyntax (regression from 0.23.1) #341

Description

@dmealing

Found upgrading an adopter project from 0.23.1 to 0.24.0 (GA).

Summary

@metaobjectsdev/codegen-ts emits an enum's type and its Zod value in a single value
import:

import { DispositionEnum, DispositionEnumEnum } from "./enums";

DispositionEnum is a type; only DispositionEnumEnum is a runtime value. Under
verbatimModuleSyntax: true — the default in the current Vite + TS project templates — that is
a hard error, so tsc fails on generated code the adopter cannot edit.

Observed

src/generated/DispositionChangeView.ts(5,10): error TS1484: 'DispositionEnum' is a type and must
  be imported using a type-only import when 'verbatimModuleSyntax' is enabled.

12 such errors across 9 generated files in one project. Every one is in src/generated/.

The two symbols come from the generator's own enums.ts, which is unambiguous about which is
which:

export type  DispositionEnum     = "friendly" | "neutral" | "hostile" | "romantic";
export const DispositionEnumEnum = z.enum([...]);

Affected symbols in this project: DispositionEnum, EquipmentSlotEnum, ActionTypeEnum,
DifficultyEnum, MemoryCategoryEnum — i.e. any field.enum referenced from a generated view.

Why it did not show up everywhere

Two sibling apps in the same repository consume the same generator. Only one fails, and the
difference is exactly one setting:

app verbatimModuleSyntax tsc
app A unset passes
app B true (in tsconfig.app.json and tsconfig.node.json) 12 errors

So the bug is invisible to any project that has not enabled it, which is presumably why it
shipped. It is a regression against 0.23.1, where the same project's tsc -b exited 0.

Suggested fix

Split the emission by kind:

import type { DispositionEnum } from "./enums";
import { DispositionEnumEnum } from "./enums";

Or emit import { type DispositionEnum, DispositionEnumEnum } from "./enums";, which is
equivalent and keeps it to one statement. Either form is also correct when
verbatimModuleSyntax is off, so there is no need to detect the setting.

Worth a generator test compiled with verbatimModuleSyntax: true, since that is the only
configuration in which this class of defect is visible at all — a type/value split emitted
wrongly is silently fine everywhere else.

Workaround for adopters today

None that is not a downgrade. The files are generated, so they cannot be hand-fixed durably; the
only lever is turning verbatimModuleSyntax off, which weakens the project's own type-safety
settings to accommodate generated code. Projects with it enabled are effectively blocked on
0.24.0 for the TypeScript surface.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions