In TypeORM, how can I create a postgres enum type Gender as in this raw query
CREATE TYPE public.Gender AS ENUM (
'male', 'female'
);
ALTER TABLE public.person ALTER COLUMN gender TYPE public.gender USING gender::gender;
and use it in the Entity class?
I have tried
@Entity()
export class Person {
@Column('enum')
gender: 'male' | 'female'
}
but obviously this isn't the right way, since I got the error message "type enum does not exist".
I don't want to use typescript enum either, since it will give me a bunch of 0s and 1s in the database.
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;
}
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
}
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 {
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With