TypeORM 中的 Postgres 枚举

Postgres enum in TypeORM

在 TypeORM 中,如何创建一个 postgres 枚举类型 Gender,就像在这个原始查询中一样

CREATE TYPE public.Gender AS ENUM (
    'male', 'female'
);
ALTER TABLE public.person ALTER COLUMN gender TYPE public.gender USING gender::gender;

并在实体中使用它 class?

我试过了

@Entity()
export class Person {
    @Column('enum')
    gender: 'male' | 'female'
}

但显然这不是正确的方法,因为我收到错误消息“type enum does not exist”。

我也不想使用 typescript 枚举,因为它会在数据库中给我一堆 0 和 1。

编辑: 这个答案仍然有效,但有点过时了,因为 0.1.0 alpha 版本的 TypeORM 支持 PostgreSQL 和 MySQL.


PostgreSQL 有一个内置的枚举类型,但不幸的是 TypeORM 目前 only supports it for MySQL

但是,通过将 @Column 类型用作 int 并将枚举用于您的字段类型,您可以使用 int 类型枚举获得类似的结果。

enum Gender {
  Male,
  Female,
  Other
}

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

(此方法允许您在需要时使用 @IsEnum decorator from class-validator 来验证输入)

您还可以使用字符串枚举(在 TypeScript 2.4 上可用,请检查 了解旧版本),如果是这种情况,只需将数据类型更改为 string

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

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

正如已接受的答案所述,它现在在 postgres 中受支持,但仍然存在问题:Github issue,修复可能会在下一个 RC 中发布。同时,我在线程上看到了一个很好的解决方案,我什至更喜欢它而不是实际功能完全正常工作:

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 {

对于 Postgres,列类型应为 'text',而不是 'string',因为字符串结果为 DataTypeNotSupportedError:"postgres" 数据库不支持“”中的数据类型 "string"。

Postgres 的 TypeOrm 现在支持枚举

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;
}

请参阅@noam steiner 的回答,但 TypeORM 将识别枚举类型而不显式提供它,所以这就足够了:

enum SomeEnum{
  # ...
}

class Entity {
  @Field()
  @Column()
  someEnumField: SomeEnum;
}

值得一提的是,在多个实体中使用相同的枚举可能会导致奇怪的枚举属性缺失错误。我花了几个小时才弄清楚这个问题。