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 {