Skip to main content
Version: v7 - alpha

Inheritance

Model inheritance is a way to share common attributes and methods between models.

Sequelize supports a style of inheritance called Concrete Table Inheritance. This means that each non-abstract model in the hierarchy has its own table in the database:

Concrete Table Inheritance

Concrete Table Inheritance - Source

Here is how you would implement this in Sequelize:

import { Model, InferAttributes, InferCreationAttributes } from '@sequelize/core';
import { Attribute, Default, PrimaryKey, NotNull } from '@sequelize/core/decorators-legacy';
import { SqliteDialect } from '@sequelize/sqlite3';

@Table.Abstract
class Player<M extends Player = Player> extends Model<
InferAttributes<M>,
InferCreationAttributes<M>
> {
@Attribute(DataTypes.STRING)
@NotNull
declare name: string;
}

class Footballer extends Player<Footballer> {
@Attribute(DataTypes.STRING)
@NotNull
declare club: string;
}

class Cricketer<M extends Cricketer = Cricketer> extends Player<M> {
@Attribute(DataTypes.INTEGER)
@NotNull
declare battingAverage: number;
}

class Bowler extends Cricketer<Bowler> {
@Attribute(DataTypes.INTEGER)
@NotNull
declare bowlingAverage: number;
}

const sequelize = new Sequelize({
dialect: SqliteDialect,
models: [Footballer, Cricketer],
});

Abstract Models

Some models are not meant to be used directly. They are meant to be used as a base class for other models. Those models are called abstract models.

Those models should not be registered in the Sequelize instance, to prevent them from creating a table in the database. To prevent a model from being registered, you can use the @Table.Abstract decorator instead of @Table on the model class.

@Table.Abstract
abstract class BaseModel extends Model {
// ...
}

This decorator accepts the same options as the @Table decorator, except for name and tableName, as these options cannot be inherited.

Limitations

You cannot define @HasOne, @HasMany, or @BelongsToMany associations on inherited models (the parent model).

This limitation is due to the fact that these associations declare a foreign key on the target model. Having multiple models attempting to declare the same foreign key is not possible, as a foreign key can only point to a single model.

Similarly, you cannot use the inverse option on @BelongsTo associations on inherited models, as this option declares an association on the target model, whose name must be unique.