Skip to content

const enum objects not recognized in createQueryOrParamSchema (SWC compatibility) #3909

@shayanline

Description

@shayanline

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

When using SWC as the TypeScript compiler, properties typed with enums in a DTO class used as a @Query() parameter are not correctly handled. SWC resolves design:type metadata for enum properties to the actual const object at runtime (e.g., { ACTIVE: 'active', INACTIVE: 'inactive' }) rather than Object or String.

In createQueryOrParamSchema, there is no isConstEnumObject guard before isObjectLiteral. Since const enum objects pass the isObjectLiteral check, the code enters the wrong branch and attempts to treat enum values as nested schema properties, producing incorrect OpenAPI output or throwing errors.

Minimum reproduction code

// Using SWC compiler (.swcrc configured)

export enum CampaignStatus {
  ACTIVE = 'active',
  PAUSED = 'paused',
  COMPLETED = 'completed',
}

export class CampaignFilterDto {
  @ApiPropertyOptional({ description: 'Filter by status', enum: CampaignStatus })
  @IsOptional()
  @IsEnum(CampaignStatus)
  status?: CampaignStatus;
}

@Controller('campaigns')
export class CampaignController {
  @Get()
  findAll(@Query() filters: CampaignFilterDto) { ... }
}

Expected behavior

The status query parameter should produce:

{ "type": "string", "enum": ["active", "paused", "completed"] }

Analysis

PR #3802 correctly added isConstEnumObject handling in createSchemaMetadata (for @Body() / model DTO properties), but the parallel code path in createQueryOrParamSchema (for @Query() / @Param() parameters) was not updated.

Current code in schema-object-factory.tscreateQueryOrParamSchema:

// ❌ Missing: if (this.isConstEnumObject(param.type)) { ... }
if (this.isObjectLiteral(param.type)) {
    // const enums incorrectly enter this branch
}

Compare with createSchemaMetadata (already fixed):

if (this.isConstEnumObject(typeRef)) {  // ✅ Checks BEFORE isObjectLiteral
    const enumValues = getEnumValues(typeRef);
    const enumType = getEnumType(enumValues);
    // ... synthesizes correct enum metadata
}
if (this.isObjectLiteral(typeRef)) {
    // Only reached if NOT a const enum
}

Suggested fix

Add the same isConstEnumObject guard in createQueryOrParamSchema, before the isObjectLiteral check:

if (this.isConstEnumObject(param.type)) {
    const enumValues = getEnumValues(param.type);
    const enumType = getEnumType(enumValues);
    return { ...param, schema: { type: enumType, enum: enumValues }, selfRequired: param.required };
}
if (this.isObjectLiteral(param.type)) {
    // existing code...
}

Package version

  • @nestjs/swagger: 11.4.2
  • Compiler: SWC

NestJS version

11.x

Node.js version

24.x

In which operating systems have you tested?

  • Linux

Other

Related: PR #3802 (fixed createSchemaMetadata but not createQueryOrParamSchema)

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