diff --git a/docs/associations/belongs-to-many.md b/docs/associations/belongs-to-many.md index c887b6c10..ab2156c44 100644 --- a/docs/associations/belongs-to-many.md +++ b/docs/associations/belongs-to-many.md @@ -98,6 +98,59 @@ class Toot extends Model, InferCreationAttributes> { In TypeScript, you need to declare the typing of your foreign keys, but they will still be configured by Sequelize automatically. You can still, of course, use any [attribute decorator](../models/defining-models.mdx) to customize them. +### Associations with extra attributes on through table + +When creating an N:M association, for example, with User and Project through UserProjects you might want extra attributes on the junction table like the "role" attribute. +This relationship can be setup like this: + +```ts +class UserProject extends Model, InferCreationAttributes> { + @Attribute(DataTypes.STRING) + declare role: string; + + declare projectId: number; + declare userId: number; +} + +class Project extends Model, InferCreationAttributes> { + @Attribute(DataTypes.STRING) + declare name: string; + + declare UserProject?: NonAttribute; +} + +class User extends Model, InferCreationAttributes> { + @Attribute(DataTypes.STRING) + declare username: string; + + @BelongsToMany(() => Project, { + through: UserProject, + }) + declare projects?: NonAttribute; + + declare getProjects: BelongsToManyGetAssociationsMixin; + declare setProjects: BelongsToManySetAssociationsMixin; + declare addProjects: BelongsToManyAddAssociationsMixin; +} +``` + +Creating multiple associations with the same extra attributes is possible by passing a single object on the through attribute: +```ts +user1.setProjects([project1, project2, project3], { through: { role: 'admin' }}) +``` + +With the [set](#association-setter-setx) and [add](#association-adder-addx) mixins different extra attributes per association can be set by passing an array of objects of the same length as the ammount of associations: +```ts +user1.setProjects([project1, project2, project3], { + through: [ + { role: 'admin' }, + { role: 'manager' }, + { role: 'designer' }, + ] +}) +(await user1.getProducts()).map(x => x.UserProduct?.role) // [ 'admin', 'manager', 'designer' ] +``` + ## Inverse Association The `BelongsToMany` association automatically creates the inverse association on the target model, which is also a `BelongsToMany` association.