2

I have been attempting to achieve Single Table Inheritance with typeorm using Schema Definitions without success. My entities have a hierarchy with an abstract base class Attendee and would like to use an enum property named type as the discriminator.

Enum Discriminator

export enum AttendeeType {
  Member = 'member',
  Guest = 'guest',
}

Interfaces

export interface IAttendee extends IPrimaryKey {
  type: AttendeeType;
  _username?: string;
  givenName: string;
  familyName: string;
  sessionToken: string;
  isHost: boolean;
  meeting: number;
}

export interface IGuest extends IAttendee {
  test?: string;  //this is to work around empty columns not being allowed in schema definitions
}

export interface IMember extends IAttendee {
  _username?: string;
}

Schema Definitions

export const AttendeeSchema = new EntitySchema<IAttendee>({
  name: 'attendees',
  target: Attendee,  //tried setting targets explicitly to get inheritance
  columns: {
    ...primaryKeySchema,
    type: {          //no way to indicate this is the discriminator
      type: 'enum',
      enum: AttendeeType,
      nullable: false,
      default: AttendeeType.Guest,
    },
    givenName: {
      type: 'varchar',
      name: 'name_givenName',
      length: 50,
      nullable: false,
    },
    familyName: {
      type: 'varchar',
      name: 'name_familyName',
      length: 50,
      nullable: false,
    },
    vonageSessionToken: {
      type: 'varchar',
      length: 500,
      nullable: false,
    },
    isHost: {
      type: 'boolean',
      nullable: false,
      default: false,
    },
  },
  relations: {
    meeting: {
      type: 'many-to-one',
      target: Meeting,
      nullable: false,
      joinColumn: true,
      orphanedRowAction: 'delete',
    },
  },
});

export const GuestSchema = new EntitySchema<IGuest>({
  name: 'guests',
  target: Guest,
  extends: 'attendees',
  type: 'entity-child',
  columns: {
    test: {    //trying to work around failure with empty columns definition
      type: 'varchar',
      length: 10,
      nullable: true,
    },
  },
});

export const MemberSchema = new EntitySchema<IMember>({
  name: 'members',
  target: Member,
  extends: 'attendees',
  type: 'entity-child',
  columns: {
    _username: {
      type: 'varchar',
      name: 'username',
      length: 36,
      nullable: true,
    },
  },
});

I have tried setting the targets to the Entity Class implementations as well as letting it use the name as the default. Setting the schema type to entity-child should indicate that this is Single Table Inheritance, but the inheritance hierarchy is not correctly detected.

I should be able to switch to the decorator approach to allow me to continue, but I prefer keeping my domain models separate from my data representation used for persistence and hydration.

I did debug into EntitySchemaTransformer and EntityMetadatBuilder, but unfortunately could not find anything that would lead me to how STI would be configured through schema definitions.

0 Answers0