diff --git a/packages/entity/src/EntityFields.ts b/packages/entity/src/EntityFields.ts index b897662fc..0e75141e5 100644 --- a/packages/entity/src/EntityFields.ts +++ b/packages/entity/src/EntityFields.ts @@ -129,18 +129,28 @@ export class StrictEnumField< T extends object, TRequireExplicitCache extends boolean, > extends EnumField { - private readonly enum: T; + private readonly enumValues: ReadonlySet; constructor( options: TRequireExplicitCache extends true ? EntityFieldDefinitionOptionsExplicitCache & { enum: T } : EntityFieldDefinitionOptions & { enum: T }, ) { super(options); - this.enum = options.enum; + // Numeric TypeScript enums contain reverse mappings (e.g. { ADMIN: 0, 0: "ADMIN" }); + // filter out the numeric string keys so reverse-mapped names don't pass validation. + this.enumValues = new Set( + Object.entries(options.enum) + .filter(([key]) => Number.isNaN(Number(key))) + .map(([, value]) => value) + .filter( + (value): value is string | number => + typeof value === 'string' || typeof value === 'number', + ), + ); } protected override validateInputValueInternal(value: string | number): boolean { - return super.validateInputValueInternal(value) && Object.values(this.enum).includes(value); + return super.validateInputValueInternal(value) && this.enumValues.has(value); } } diff --git a/packages/entity/src/__tests__/EntityFields-test.ts b/packages/entity/src/__tests__/EntityFields-test.ts index 6bb89cabb..787b72536 100644 --- a/packages/entity/src/__tests__/EntityFields-test.ts +++ b/packages/entity/src/__tests__/EntityFields-test.ts @@ -78,12 +78,23 @@ enum TestEnum { WHO = 'wat', } +enum NumericTestEnum { + ADMIN, + USER, +} + describeFieldTestCase( new StrictEnumField({ columnName: 'wat', enum: TestEnum }), [TestEnum.HELLO, TestEnum.WHO, 'world'], ['what', 1, true], ); +describeFieldTestCase( + new StrictEnumField({ columnName: 'wat', enum: NumericTestEnum }), + [NumericTestEnum.ADMIN, NumericTestEnum.USER], + ['ADMIN', 'USER', 2, true], +); + describeFieldTestCase( new BufferField({ columnName: 'wat' }), [Buffer.from('hello')],