Postgres enum in typeorm

EDIT: This answer is still valid but a bit outdated as 0.1.0 alpha versions of TypeORM support enums for both PostgreSQL and MySQL.


PostgreSQL has a built in enum type, but unfortunately TypeORM currently only supports it for MySQL.

However, you could achieve a similar result with an int-type enum by using the @Column type as int and using the enum for your field type.

enum Gender {
  Male,
  Female,
  Other
}

@Entity()
export class Person {
    @Column('int')
    gender: Gender
}

(This approach lets you use the @IsEnum decorator from class-validator to validate the input if needed)

You could also use string enums (available on TypeScript 2.4, check Typescript `enum` from JSON string for older versions) and if that is the case just change the data type to string instead.

enum Gender {
  Male = 'male',
  Female = 'female',
  Other = 'other'
}

@Entity()
export class Person {
    @Column('text')
    gender: Gender
}

For Postgres, the column type should be 'text', not 'string', as string results in DataTypeNotSupportedError: Data type "string" in "" is not supported by "postgres" database.


Enum is now supported on TypeOrm for postgres

By the docs

enum column type is supported by postgres and mysql. There are various possible column definitions:

Using typescript enums:

export enum UserRole {
    ADMIN = "admin",
    EDITOR = "editor",
    GHOST = "ghost"
}

@Entity()
export class User {

    @PrimaryGeneratedColumn()
    id: number;

    @Column({
        type: "enum",
        enum: UserRole,
        default: UserRole.GHOST
    })
    role: UserRole;

}

Using array with enum values:

export type UserRoleType = "admin" | "editor" | "ghost",

@Entity()
export class User {

    @PrimaryGeneratedColumn()
    id: number;

    @Column({
        type: "enum",
        enum: ["admin", "editor", "ghost"],
        default: "ghost"
    })
    role: UserRoleType;
}

As the accepted answer states, it is now supported in postgres but still buggy: Github issue, the fix will be released in the next RC probably. Meanwhile, I saw on the thread a nice solution which I even liked it more than the actual feature fully working:

fwiw I've been using string enum with check constraint. It's a lot more flexible than actual postgres enum, which creates whole new data types in postgres index and are really hard to manage (alter table, etc.)

export function CheckEnum(tableName: string, fieldName: string, enumValue: any) {
  // Hash enum value and put it as part of constraint name so we can
  // force typeorm to generate migration for enum changes.
  const hash = crypto
    .createHash('sha1')
    .update(Object.values(enumValue).join(''))
    .digest('hex')
  return Check(
    // https://til.hashrocket.com/posts/8f87c65a0a-postgresqls-max-identifier-length-is-63-bytes
    `cke_${tableName}_${fieldName}_${hash}`.slice(0, 63),
    `${fieldName} in (${Object.values(enumValue).map(t => `'${t}'`)})`,
  )
}

And use it like so

export enum Gender {
  Male = 'male',
  Female = 'female',
  Other = 'other'
}

@Entity()
@CheckEnum('person', 'gender', Gender)
export class Person {