Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't enforce type restrictions on mysqlEnum and pgEnum to be non-empty arrays #2429

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

aprilmintacpineda
Copy link

@aprilmintacpineda aprilmintacpineda commented Jun 3, 2024

Summary of changes

  • Removed type restriction on non-empty arrays on mysqlEnum
  • Removed type restriction on non-empty arrays on pgEnum
  • Added check to ensure that values parameter for pgEnum is not an empty array, if it is, throw an error.

Related discussion: #1914

Problem:

mysqlEnum and pgEnum both expect the 2nd argument to be of type [string, ...string[]] which means it ensures that we are not passing an empty array to it. However, this would only work smoothly for arrays but not for enums. To get around the limitation, we always have to use the as keyword like so:

mysqlEnum(
  'type',
  Object.values(eCategoryType) as [
    eCategoryType,
    ...eCategoryType[],
  ],
).notNull()

Reason being is because Object.values(eCategoryType) becomes a type of eCategoryType[] which doesn't fit what we are explicitly checking for [eCategoryType, ...eCategoryType[]].

I understand that this restriction was put in place to ensure that no one passes an empty array in there. In this case, I think we can add that kind of restriction in-code rather than in-type -- which looking at the mysqlEnum code, we are already doing by checking values.length === 0.

Note

I saw on some other files that enums are generally expected as [string, ...string[]], these other places are not covered in this PR, this only aims to fix the issue on mysqlEnum and pgEnum.

What will work

enums will work -- now without needing to use as keyword.

image

Regular arrays will still work

image

Empty arrays will now work -- previously there will be a TS error. However, in-code validation will prevent this from happening and throw an error.

image

Patch Package

You can use patch-package to apply the fix right now.

Step 1

yarn add -D patch-package

Step 2

2.1. cd /to/root/of/your/project
2.2. touch patches/drizzle-orm+0.31.0.patch

Step 3

Copy the contents below to the file you just created

patches/drizzle-orm+0.31.0.patch
diff --git a/node_modules/drizzle-orm/mysql-core/columns/enum.d.ts b/node_modules/drizzle-orm/mysql-core/columns/enum.d.ts
index 274c06a..9a6d67c 100644
--- a/node_modules/drizzle-orm/mysql-core/columns/enum.d.ts
+++ b/node_modules/drizzle-orm/mysql-core/columns/enum.d.ts
@@ -3,7 +3,7 @@ import type { ColumnBaseConfig } from "../../column.js";
 import { entityKind } from "../../entity.js";
 import type { Writable } from "../../utils.js";
 import { MySqlColumn, MySqlColumnBuilder } from "./common.js";
-export type MySqlEnumColumnBuilderInitial<TName extends string, TEnum extends [string, ...string[]]> = MySqlEnumColumnBuilder<{
+export type MySqlEnumColumnBuilderInitial<TName extends string, TEnum extends string[]> = MySqlEnumColumnBuilder<{
     name: TName;
     dataType: 'string';
     columnType: 'MySqlEnumColumn';
@@ -24,4 +24,4 @@ export declare class MySqlEnumColumn<T extends ColumnBaseConfig<'string', 'MySql
     readonly enumValues: T["enumValues"];
     getSQLType(): string;
 }
-export declare function mysqlEnum<TName extends string, U extends string, T extends Readonly<[U, ...U[]]>>(name: TName, values: T | Writable<T>): MySqlEnumColumnBuilderInitial<TName, Writable<T>>;
+export declare function mysqlEnum<TName extends string, U extends string, T extends ReadonlyArray<U>>(name: TName, values: T | Writable<T>): MySqlEnumColumnBuilderInitial<TName, Writable<T>>;
diff --git a/node_modules/drizzle-orm/pg-core/columns/enum.d.ts b/node_modules/drizzle-orm/pg-core/columns/enum.d.ts
index 357f708..c240362 100644
--- a/node_modules/drizzle-orm/pg-core/columns/enum.d.ts
+++ b/node_modules/drizzle-orm/pg-core/columns/enum.d.ts
@@ -1,10 +1,10 @@
 import type { ColumnBuilderBaseConfig } from "../../column-builder.js";
 import type { ColumnBaseConfig } from "../../column.js";
 import { entityKind } from "../../entity.js";
-import type { AnyPgTable } from "../table.js";
 import type { Writable } from "../../utils.js";
+import type { AnyPgTable } from "../table.js";
 import { PgColumn, PgColumnBuilder } from "./common.js";
-export type PgEnumColumnBuilderInitial<TName extends string, TValues extends [string, ...string[]]> = PgEnumColumnBuilder<{
+export type PgEnumColumnBuilderInitial<TName extends string, TValues extends string[]> = PgEnumColumnBuilder<{
     name: TName;
     dataType: 'string';
     columnType: 'PgEnumColumn';
@@ -12,15 +12,15 @@ export type PgEnumColumnBuilderInitial<TName extends string, TValues extends [st
     enumValues: TValues;
     driverParam: string;
 }>;
-export interface PgEnum<TValues extends [string, ...string[]]> {
+export interface PgEnum<TValues extends string[]> {
     <TName extends string>(name: TName): PgEnumColumnBuilderInitial<TName, TValues>;
     readonly enumName: string;
     readonly enumValues: TValues;
     readonly schema: string | undefined;
 }
-export declare function isPgEnum(obj: unknown): obj is PgEnum<[string, ...string[]]>;
+export declare function isPgEnum(obj: unknown): obj is PgEnum<string[]>;
 export declare class PgEnumColumnBuilder<T extends ColumnBuilderBaseConfig<'string', 'PgEnumColumn'> & {
-    enumValues: [string, ...string[]];
+    enumValues: string[];
 }> extends PgColumnBuilder<T, {
     enum: PgEnum<T['enumValues']>;
 }> {
@@ -28,7 +28,7 @@ export declare class PgEnumColumnBuilder<T extends ColumnBuilderBaseConfig<'stri
     constructor(name: string, enumInstance: PgEnum<T['enumValues']>);
 }
 export declare class PgEnumColumn<T extends ColumnBaseConfig<'string', 'PgEnumColumn'> & {
-    enumValues: [string, ...string[]];
+    enumValues: string[];
 }> extends PgColumn<T, {
     enum: PgEnum<T['enumValues']>;
 }> {
@@ -40,4 +40,4 @@ export declare class PgEnumColumn<T extends ColumnBaseConfig<'string', 'PgEnumCo
     }>, config: PgEnumColumnBuilder<T>['config']);
     getSQLType(): string;
 }
-export declare function pgEnum<U extends string, T extends Readonly<[U, ...U[]]>>(enumName: string, values: T | Writable<T>): PgEnum<Writable<T>>;
+export declare function pgEnum<U extends string, T extends ReadonlyArray<U>>(enumName: string, values: T | Writable<T>): PgEnum<Writable<T>>;

Step 4

yarn patch-package

Step 5

Update your package.json file to the following:

"scripts": {
  // ... your other scripts
  "postinstall": "yarn patch-package"
},

@aprilmintacpineda aprilmintacpineda changed the title Don't enforce restrictions on enums being non-empty arrays? Don't enforce type restrictions on enums to be non-empty arrays Jun 3, 2024
@aprilmintacpineda aprilmintacpineda changed the title Don't enforce type restrictions on enums to be non-empty arrays Don't enforce type restrictions on mysqlEnum and pgEnum to be non-empty arrays Jun 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant