Skip to content

Decimal-looking x-enum-varnames emitted as numeric JS keys, breaking z.nativeEnum #3941

@AwkEng

Description

@AwkEng

Description

When an OpenAPI integer enum has x-enum-varnames whose entries look like decimal numbers (e.g. CFR section numbers like \"22.537\"), the generated TypeScript const uses unquoted decimal literals as property keys. JavaScript parses these as numeric keys, which then breaks the generated z.nativeEnum call from the zod plugin (which requires string-keyed enums).

Reproduction

Schema fragment:

```json
{
"FccPart22Section": {
"enum": [1, 2],
"type": "integer",
"x-enum-varnames": ["22.537", "22.567"]
}
}
```

Config:

```ts
import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
input: 'openapi.json',
output: 'src/generated',
plugins: [
{
name: '@hey-api/typescript',
enums: { enabled: true, mode: 'javascript', case: 'preserve' },
},
{ name: 'zod', compatibilityVersion: 3, definitions: true },
],
});
```

Actual output

`types.gen.ts`:

```ts
export const FccPart22Section = {
22.537: 1,
22.567: 2,
} as const;
export type FccPart22Section = typeof FccPart22Section[keyof typeof FccPart22Section];
```

`zod.gen.ts`:

```ts
export const zFccPart22Section = z.nativeEnum(FccPart22Section);
```

TypeScript error:

```
error TS2345: Argument of type '{ readonly 22.537: 1; readonly 22.567: 2; }' is not assignable to parameter of type 'EnumLike'.
Property '22.537' is incompatible with index signature.
Type 'number' is not assignable to type 'string'.
```

Expected output

Quote the keys so they're string-typed:

```ts
export const FccPart22Section = {
"22.537": 1,
"22.567": 2,
} as const;
```

That would satisfy `z.nativeEnum`'s `EnumLike` constraint and (correctly) preserve the varnames as string keys regardless of whether they look numeric.

Version

`@hey-api/openapi-ts` 0.97.3
`zod` ^4.0.0
TypeScript 6.0.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions