Skip to content

feat(plugin): auto-generate enum metadata for string and number literal union types#3885

Merged
kamilmysliwiec merged 3 commits into
nestjs:masterfrom
y-hsgw:feat/plugin-string-literal-union-enum
May 1, 2026
Merged

feat(plugin): auto-generate enum metadata for string and number literal union types#3885
kamilmysliwiec merged 3 commits into
nestjs:masterfrom
y-hsgw:feat/plugin-string-literal-union-enum

Conversation

@y-hsgw

@y-hsgw y-hsgw commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Revisits #1665.

In issue #1665, the feature was closed with "There are no plans to support this feature atm." However, after investigating the implementation, it appears feasible with a relatively small change. I'd like to propose this as a candidate for support — happy to iterate if the approach needs adjustment.

What this does

The CLI plugin now automatically infers enum: [...] metadata for properties whose type is a string or number literal union — without requiring a manual @ApiProperty({ enum: [...] }).

Before

type Color = 'red' | 'green' | 'blue';

export class CatDto {
  // Previously required manual annotation:
  @ApiProperty({ enum: ['red', 'green', 'blue'] })
  color: Color;
}

After

type Color = 'red' | 'green' | 'blue';

export class CatDto {
  color: Color;
}

Generated metadata: { color: { required: true, enum: ["red", "green", "blue"] } }

Cases covered

Type Generated metadata
'a' | 'b' enum: ["a", "b"]
'a' | 'b' | null enum: ["a", "b"], nullable: true
Color (type alias) enum: ["red", "green", "blue"]
Color | null enum: ["red", "green", "blue"], nullable: true
Color? (optional) required: false, enum: [...]
1 | 2 | 3 enum: [1, 2, 3]
TypeScript enum unchanged (existing behavior preserved)

Implementation

  • lib/plugin/utils/plugin-utils.ts: Added getStringLiteralUnionValues() — detects whether a ts.Type is a pure string or number literal union (TypeScript enum members are explicitly excluded via SymbolFlags.EnumMember), and returns the values along with a isNullable flag.
  • lib/plugin/visitors/model-class.visitor.ts:
    • createTypePropertyAssignments: treats string/number literal unions like enums (skips emitting type: () => Object; emits nullable: true when needed)
    • createEnumPropertyAssignment: when a literal union is detected, emits enum: ["a", "b", ...] or enum: [1, 2, ...] as an ArrayLiteralExpression instead of a type reference identifier

Non-goals / out of scope

  • Mixed unions like 'a' | 1 | true — To keep the diff small, and since this is still a proposal, this currently only supports simple unions where all members are string literals or all members are number literals.

@y-hsgw y-hsgw changed the title feat(plugin): auto-generate enum metadata for string literal union types feat(plugin): auto-generate enum metadata for string and number literal union types Apr 30, 2026
@kamilmysliwiec kamilmysliwiec merged commit d3c5f86 into nestjs:master May 1, 2026
1 check passed
@kamilmysliwiec

Copy link
Copy Markdown
Member

lgtm, great PR!

@y-hsgw y-hsgw deleted the feat/plugin-string-literal-union-enum branch May 1, 2026 07:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants