class-validator icon indicating copy to clipboard operation
class-validator copied to clipboard

fix: `@IsEnum()` does not error when enum-key is used instead of enum-value

Open MickL opened this issue 4 years ago • 2 comments

Description

When using an enum-key instead of enum-value it should throw an error but doesnt.

enum Direction {
  Up = 0,
  Down,
  Left,
  Right,
}

class myClass {
  @IsEnum(Direction)
  direction: Direction;
}

Now the following will be valid: const obj = { direction: 'Down'; }

Expected behavior

It should add an error.

Actual behavior

Does not add an error.

Workaround

Use IsIn() instead, e.g. by use of ts-enum-util to create an array of the enum-values:

class myClass {
  @IsIn($enum(Direction).getValues())
  direction: Direction;
}

Results in:

isIn: 'direction must be one of the following values: 0, 1, 2, 3'

MickL avatar May 05 '21 13:05 MickL

Confirmed for 0.14.0.

The minimal reproduction case:

import { IsEnum, validate } from 'class-validator';

enum Direction {
  Up = 0,
  Down,
  Left,
  Right,
}

class MyPayload {
  @IsEnum(Direction)
  value: Direction;

  constructor(direction?: Direction) {
    this.value = direction;
  }
}

// Will pass
validate(new MyPayload(Direction.Up)).then(console.log);
validate(new MyPayload(Direction.Down)).then(console.log);
// SHOULD FAIL
validate(new MyPayload('Up' as any as Direction)).then(console.log);
validate(new MyPayload('Down' as any as Direction)).then(console.log);

NoNameProvided avatar Dec 09 '22 19:12 NoNameProvided

Bumped into the same issue, version 0.14.0

enum MyEnum {
  Alpha = 1,
  Beta = 2,
}

class TestClass {
  @IsEnum(MyEnum)
  myEnumVal: any;
}
const inst = new TestClass();
inst.myEnumVal = 'Alpha';
console.log(validateSync(inst));

The issue comes from the function:

export function isEnum(value: unknown, entity: any): boolean {
  const enumValues = Object.keys(entity).map(k => entity[k]);
  return enumValues.includes(value);
}

Specifically this line

const enumValues = Object.keys(entity).map(k => entity[k]);

An enum will become this in javascript:

var MyEnum;
(function (MyEnum) {
    MyEnum[MyEnum["Alpha"] = 1] = "Alpha";
    MyEnum[MyEnum["Beta"] = 2] = "Beta";
})(MyEnum || (MyEnum = {}));

When running Object.keys(MyEnum) we will get this:

Object.keys(MyEnum)
['1', '2', 'Alpha', 'Beta']

vilkatis avatar Jun 15 '23 18:06 vilkatis