{"id":13813148,"url":"https://github.com/sequelize/sequelize-typescript","last_synced_at":"2026-01-15T22:18:08.000Z","repository":{"id":37004107,"uuid":"50502690","full_name":"sequelize/sequelize-typescript","owner":"sequelize","description":"Decorators and some other features for sequelize","archived":false,"fork":false,"pushed_at":"2024-04-20T03:54:41.000Z","size":7207,"stargazers_count":2837,"open_issues_count":264,"forks_count":285,"subscribers_count":28,"default_branch":"master","last_synced_at":"2026-01-13T04:11:50.067Z","etag":null,"topics":["annotations","decorators","orm","sequelize","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sequelize.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-01-27T11:25:52.000Z","updated_at":"2026-01-11T15:54:13.000Z","dependencies_parsed_at":"2023-01-17T12:32:51.974Z","dependency_job_id":"7bb91e63-70d4-49f1-bc63-9fafe360de37","html_url":"https://github.com/sequelize/sequelize-typescript","commit_stats":{"total_commits":902,"total_committers":93,"mean_commits":9.698924731182796,"dds":0.6707317073170731,"last_synced_commit":"8ded61aa26e192b455c682377d45cef0582e11e2"},"previous_names":["robinbuschmann/sequelize-typescript"],"tags_count":87,"template":false,"template_full_name":null,"purl":"pkg:github/sequelize/sequelize-typescript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequelize%2Fsequelize-typescript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequelize%2Fsequelize-typescript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequelize%2Fsequelize-typescript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequelize%2Fsequelize-typescript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sequelize","download_url":"https://codeload.github.com/sequelize/sequelize-typescript/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequelize%2Fsequelize-typescript/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28472625,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-15T22:13:38.078Z","status":"ssl_error","status_checked_at":"2026-01-15T22:12:11.737Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["annotations","decorators","orm","sequelize","typescript"],"created_at":"2024-08-04T04:01:04.682Z","updated_at":"2026-01-15T22:18:07.981Z","avatar_url":"https://github.com/sequelize.png","language":"TypeScript","readme":"# sequelize-typescript\n\n[![Build Status](https://github.com/sequelize/sequelize-typescript/workflows/Node.js%20CI/badge.svg)](https://github.com/sequelize/sequelize-typescript/actions?query=workflow%3A%22Node.js+CI%22)\n[![codecov](https://codecov.io/gh/sequelize/sequelize-typescript/branch/master/graph/badge.svg)](https://codecov.io/gh/sequelize/sequelize-typescript)\n[![NPM](https://img.shields.io/npm/v/sequelize-typescript.svg)](https://www.npmjs.com/package/sequelize-typescript)\n\nDecorators and some other features for sequelize (v6).\n\n- [Installation](#installation)\n- [Model Definition](#model-definition)\n  - [`@Table` API](#table-api)\n  - [`@Column` API](#column-api)\n- [Usage](#usage)\n  - [Configuration](#configuration)\n  - [globs](#globs)\n  - [Model-path resolving](#model-path-resolving)\n- [Model association](#model-association)\n  - [One-to-many](#one-to-many)\n  - [Many-to-many](#many-to-many)\n  - [One-to-one](#one-to-one)\n  - [`@ForeignKey`, `@BelongsTo`, `@HasMany`, `@HasOne`, `@BelongsToMany` API](#foreignkey-belongsto-hasmany-hasone-belongstomany-api)\n  - [Generated getter and setter](#type-safe-usage-of-auto-generated-functions)\n  - [Multiple relations of same models](#multiple-relations-of-same-models)\n- [Indexes](#indexes)\n  - [`@Index` API](#index)\n  - [`createIndexDecorator()` API](#createindexdecorator)\n- [Repository mode](#repository-mode)\n  - [How to enable repository mode?](#how-to-enable-repository-mode)\n  - [How to use repository mode?](#how-to-use-repository-mode)\n  - [How to use associations with repository mode?](#how-to-use-associations-with-repository-mode)\n  - [Limitations of repository mode](#limitations-of-repository-mode)\n- [Model validation](#model-validation)\n- [Scopes](#scopes)\n- [Hooks](#hooks)\n- [Why `() =\u003e Model`?](#why---model)\n- [Recommendations and limitations](#recommendations-and-limitations)\n\n## Installation\n\n- this assumes usage of `sequelize@6`\n- _sequelize-typescript_ requires [sequelize](https://github.com/sequelize/sequelize)\n- additional typings as documented [here](https://sequelize.org/master/manual/typescript.html) and [reflect-metadata](https://www.npmjs.com/package/reflect-metadata)\n\n```sh\nnpm install --save-dev @types/node @types/validator\nnpm install sequelize reflect-metadata sequelize-typescript\n```\n\nYour `tsconfig.json` needs the following flags:\n\n```json\n\"target\": \"es6\", // or a more recent ecmascript version\n\"experimentalDecorators\": true,\n\"emitDecoratorMetadata\": true\n```\n\n### Sequelize Options\n\n- `SequelizeConfig` renamed to `SequelizeOptions`\n- `modelPaths` property renamed to `models`\n\n### Scopes Options\n\nThe `@Scopes` and `@DefaultScope` decorators now take lambda's as options\n\n```ts\n@DefaultScope(() =\u003e ({...}))\n@Scopes(() =\u003e ({...}))\n```\n\ninstead of deprecated way:\n\n```ts\n@DefaultScope({...})\n@Scopes({...}))\n```\n\n## Model definition\n\n```typescript\nimport { Table, Column, Model, HasMany } from 'sequelize-typescript';\n\n@Table\nclass Person extends Model {\n  @Column\n  name: string;\n\n  @Column\n  birthday: Date;\n\n  @HasMany(() =\u003e Hobby)\n  hobbies: Hobby[];\n}\n```\n\n### Less strict\n\n```typescript\nimport { Table, Model } from 'sequelize-typescript';\n\n@Table\nclass Person extends Model {}\n```\n\n### More strict\n\n```typescript\nimport { Optional } from 'sequelize';\nimport { Table, Model } from 'sequelize-typescript';\n\ninterface PersonAttributes {\n  id: number;\n  name: string;\n}\n\ninterface PersonCreationAttributes extends Optional\u003cPersonAttributes, 'id'\u003e {}\n\n@Table\nclass Person extends Model\u003cPersonAttributes, PersonCreationAttributes\u003e {}\n```\n\nThe model needs to extend the `Model` class and has to be annotated with the `@Table` decorator. All properties that\nshould appear as a column in the database require the `@Column` annotation.\n\nSee more advanced example [here](https://github.com/RobinBuschmann/sequelize-typescript-example).\n\n### `@Table`\n\nThe `@Table` annotation can be used without passing any parameters. To specify some more define options, use\nan object literal (all [define options](https://sequelize.org/v5/manual/models-definition.html#configuration)\nfrom sequelize are valid):\n\n```typescript\n@Table({\n  timestamps: true,\n  ...\n})\nclass Person extends Model {}\n```\n\n#### Table API\n\n| Decorator                        | Description                                                                                                                                                                                                            |\n| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `@Table`                         | sets `options.tableName=\u003cCLASS_NAME\u003e` and `options.modelName=\u003cCLASS_NAME\u003e` automatically                                                                                                                               |\n| `@Table(options: DefineOptions)` | sets [define options](https://sequelize.org/v5/manual/models-definition.html#configuration) (also sets `options.tableName=\u003cCLASS_NAME\u003e` and `options.modelName=\u003cCLASS_NAME\u003e` if not already defined by define options) |\n\n#### Primary key\n\nA primary key (`id`) will be inherited from base class `Model`. This primary key is by default an `INTEGER` and has\n`autoIncrement=true` (This behaviour is a native sequelize thing). The id can easily be overridden by marking another\nattribute as primary key. So either set `@Column({primaryKey: true})` or use `@PrimaryKey` together with `@Column`.\n\n#### `@CreatedAt`, `@UpdatedAt`, `@DeletedAt`\n\nAnnotations to define custom and type safe `createdAt`, `updatedAt` and `deletedAt` attributes:\n\n```typescript\n  @CreatedAt\n  creationDate: Date;\n\n  @UpdatedAt\n  updatedOn: Date;\n\n  @DeletedAt\n  deletionDate: Date;\n```\n\n| Decorator    | Description                                                            |\n| ------------ | ---------------------------------------------------------------------- |\n| `@CreatedAt` | sets `timestamps=true` and `createdAt='creationDate'`                  |\n| `@UpdatedAt` | sets `timestamps=true` and `updatedAt='updatedOn'`                     |\n| `@DeletedAt` | sets `timestamps=true`, `paranoid=true` and `deletedAt='deletionDate'` |\n\n### `@Column`\n\nThe `@Column` annotation can be used without passing any parameters. But therefore it is necessary that\nthe js type can be inferred automatically (see [Type inference](#type-inference) for details).\n\n```typescript\n  @Column\n  name: string;\n```\n\nIf the type cannot or should not be inferred, use:\n\n```typescript\nimport {DataType} from 'sequelize-typescript';\n\n  @Column(DataType.TEXT)\n  name: string;\n```\n\nOr for a more detailed column description, use an object literal\n(all [attribute options](https://sequelize.org/v5/manual/models-definition.html#configuration)\nfrom sequelize are valid):\n\n```typescript\n  @Column({\n    type: DataType.FLOAT,\n    comment: 'Some value',\n    ...\n  })\n  value: number;\n```\n\n#### Column API\n\n| Decorator                            | Description                                                                                               |\n| ------------------------------------ | --------------------------------------------------------------------------------------------------------- |\n| `@Column`                            | tries to infer [dataType](https://sequelize.org/v5/manual/models-definition.html#data-types) from js type |\n| `@Column(dataType: DataType)`        | sets [dataType](https://sequelize.org/v5/manual/models-definition.html#data-types) explicitly             |\n| `@Column(options: AttributeOptions)` | sets [attribute options](https://sequelize.org/v5/manual/models-definition.html#configuration)            |\n\n#### _Shortcuts_\n\nIf you're in love with decorators: _sequelize-typescript_ provides some more of them. The following decorators can be\nused together with the @Column annotation to make some attribute options easier available:\n\n| Decorator                         | Description                                      | Options                                                                                                                          |\n| --------------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- |\n| `@AllowNull(allowNull?: boolean)` | sets `attribute.allowNull` (default is `true`)   |\n| `@AutoIncrement`                  | sets `attribute.autoIncrement=true`              |\n| `@Unique(options? UniqueOptions)` | sets `attribute.unique=true`                     | [UniqueOptions](https://github.com/sequelize/sequelize-typescript/blob/master/src/model/column/column-options/unique.ts#L3) |\n| `@Default(value: any)`            | sets `attribute.defaultValue` to specified value |\n| `@PrimaryKey`                     | sets `attribute.primaryKey=true`                 |\n| `@Comment(value: string)`         | sets `attribute.comment` to specified string     |\n| Validate annotations              | see [Model validation](#model-validation)        |\n\n### Type inference\n\nThe following types can be automatically inferred from javascript type. Others have to be defined explicitly.\n\n| Design type | Sequelize data type |\n| ----------- | ------------------- |\n| `string`    | `STRING`            |\n| `boolean`   | `BOOLEAN`           |\n| `number`    | `INTEGER`           |\n| `bigint`    | `BIGINT`            |\n| `Date`      | `DATE`              |\n| `Buffer`    | `BLOB`              |\n\n### Accessors\n\nGet/set accessors do work as well\n\n```typescript\n@Table\nclass Person extends Model {\n  @Column\n  get name(): string {\n    return 'My name is ' + this.getDataValue('name');\n  }\n\n  set name(value: string) {\n    this.setDataValue('name', value);\n  }\n}\n```\n\n## Usage\n\nExcept for minor variations _sequelize-typescript_ will work like pure sequelize.\n(See sequelize [docs](https://docs.sequelizejs.com/manual/tutorial/models-usage.html))\n\n### Configuration\n\nTo make the defined models available, you have to configure a `Sequelize` instance from `sequelize-typescript`(!).\n\n```typescript\nimport { Sequelize } from 'sequelize-typescript';\n\nconst sequelize = new Sequelize({\n  database: 'some_db',\n  dialect: 'sqlite',\n  username: 'root',\n  password: '',\n  storage: ':memory:',\n  models: [__dirname + '/models'], // or [Player, Team],\n});\n```\n\nBefore you can use your models you have to tell sequelize where they can be found. So either set `models` in the\nsequelize config or add the required models later on by calling `sequelize.addModels([Person])` or\n`sequelize.addModels([__dirname + '/models'])`:\n\n```typescript\nsequelize.addModels([Person]);\nsequelize.addModels(['path/to/models']);\n```\n\n### globs\n\n```typescript\nimport {Sequelize} from 'sequelize-typescript';\n\nconst sequelize =  new Sequelize({\n        ...\n        models: [__dirname + '/**/*.model.ts']\n});\n// or\nsequelize.addModels([__dirname + '/**/*.model.ts']);\n```\n\n#### Model-path resolving\n\nA model is matched to a file by its filename. E.g.\n\n```typescript\n// File User.ts matches the following exported model.\nexport class User extends Model {}\n```\n\nThis is done by comparison of the filename against all exported members. The\nmatching can be customized by specifying the `modelMatch` function in the\nconfiguration object.\n\nFor example, if your models are named `user.model.ts`, and your class is called\n`User`, you can match these two by using the following function:\n\n```typescript\nimport {Sequelize} from 'sequelize-typescript';\n\nconst sequelize =  new Sequelize({\n  models: [__dirname + '/models/**/*.model.ts']\n  modelMatch: (filename, member) =\u003e {\n    return filename.substring(0, filename.indexOf('.model')) === member.toLowerCase();\n  },\n});\n```\n\nFor each file that matches the `*.model.ts` pattern, the `modelMatch` function\nwill be called with its exported members. E.g. for the following file\n\n```TypeScript\n//user.model.ts\nimport {Table, Column, Model} from 'sequelize-typescript';\n\nexport const UserN = 'Not a model';\nexport const NUser = 'Not a model';\n\n@Table\nexport class User extends Model {\n\n  @Column\n  nickname: string;\n}\n```\n\nThe `modelMatch` function will be called three times with the following arguments.\n\n```text\nuser.model UserN -\u003e false\nuser.model NUser -\u003e false\nuser.model User  -\u003e true (User will be added as model)\n```\n\nAnother way to match model to file is to make your model the default export.\n\n```TypeScript\nexport default class User extends Model {}\n```\n\n\u003e ⚠️ When using paths to add models, keep in mind that they will be loaded during runtime. This means that the path\n\u003e may differ from development time to execution time. For instance, using `.ts` extension within paths will only work\n\u003e together with [ts-node](https://github.com/TypeStrong/ts-node).\n\n### Build and create\n\nInstantiation and inserts can be achieved in the good old sequelize way\n\n```typescript\nconst person = Person.build({ name: 'bob', age: 99 });\nperson.save();\n\nPerson.create({ name: 'bob', age: 99 });\n```\n\nbut _sequelize-typescript_ also makes it possible to create instances with `new`:\n\n```typescript\nconst person = new Person({ name: 'bob', age: 99 });\nperson.save();\n```\n\n### Find and update\n\nFinding and updating entries does also work like using native sequelize. So see sequelize\n[docs](https://docs.sequelizejs.com/manual/tutorial/models-usage.html) for more details.\n\n```typescript\nPerson.findOne().then((person) =\u003e {\n  person.age = 100;\n  return person.save();\n});\n\nPerson.update(\n  {\n    name: 'bobby',\n  },\n  { where: { id: 1 } }\n).then(() =\u003e {});\n```\n\n## Model association\n\nRelations can be described directly in the model by the `@HasMany`, `@HasOne`, `@BelongsTo`, `@BelongsToMany`\nand `@ForeignKey` annotations.\n\n### One-to-many\n\n```typescript\n@Table\nclass Player extends Model {\n  @Column\n  name: string;\n\n  @Column\n  num: number;\n\n  @ForeignKey(() =\u003e Team)\n  @Column\n  teamId: number;\n\n  @BelongsTo(() =\u003e Team)\n  team: Team;\n}\n\n@Table\nclass Team extends Model {\n  @Column\n  name: string;\n\n  @HasMany(() =\u003e Player)\n  players: Player[];\n}\n```\n\nThat's all, _sequelize-typescript_ does everything else for you. So when retrieving a team by `find`\n\n```typescript\nTeam.findOne({ include: [Player] }).then((team) =\u003e {\n  team.players.forEach((player) =\u003e console.log(`Player ${player.name}`));\n});\n```\n\nthe players will also be resolved (when passing `include: Player` to the find options)\n\n### Many-to-many\n\n```typescript\n@Table\nclass Book extends Model {\n  @BelongsToMany(() =\u003e Author, () =\u003e BookAuthor)\n  authors: Author[];\n}\n\n@Table\nclass Author extends Model {\n  @BelongsToMany(() =\u003e Book, () =\u003e BookAuthor)\n  books: Book[];\n}\n\n@Table\nclass BookAuthor extends Model {\n  @ForeignKey(() =\u003e Book)\n  @Column\n  bookId: number;\n\n  @ForeignKey(() =\u003e Author)\n  @Column\n  authorId: number;\n}\n```\n\n#### Type safe _through_-table instance access\n\nTo access the _through_-table instance (instanceOf `BookAuthor` in the upper example) type safely, the type\nneed to be set up manually. For `Author` model it can be achieved like so:\n\n```ts\n  @BelongsToMany(() =\u003e Book, () =\u003e BookAuthor)\n  books: Array\u003cBook \u0026 {BookAuthor: BookAuthor}\u003e;\n```\n\n### One-to-one\n\nFor one-to-one use `@HasOne(...)`(foreign key for the relation exists on the other model) and\n`@BelongsTo(...)` (foreign key for the relation exists on this model)\n\n### `@ForeignKey`, `@BelongsTo`, `@HasMany`, `@HasOne`, `@BelongsToMany` API\n\n| Decorator                                                                                                                     | Description                                                                                                                                                                                                    |\n| ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `@ForeignKey(relatedModelGetter: () =\u003e typeof Model)`                                                                         | marks property as `foreignKey` for related class                                                                                                                                                               |\n| `@BelongsTo(relatedModelGetter: () =\u003e typeof Model)`                                                                          | sets `SourceModel.belongsTo(RelatedModel, ...)` while `as` is key of annotated property and `foreignKey` is resolved from source class                                                                         |\n| `@BelongsTo(relatedModelGetter: () =\u003e typeof Model, foreignKey: string)`                                                      | sets `SourceModel.belongsTo(RelatedModel, ...)` while `as` is key of annotated property and `foreignKey` is explicitly specified value                                                                         |\n| `@BelongsTo(relatedModelGetter: () =\u003e typeof Model, options: AssociationOptionsBelongsTo)`                                    | sets `SourceModel.belongsTo(RelatedModel, ...)` while `as` is key of annotated property and `options` are additional association options                                                                       |\n| `@HasMany(relatedModelGetter: () =\u003e typeof Model)`                                                                            | sets `SourceModel.hasMany(RelatedModel, ...)` while `as` is key of annotated property and `foreignKey` is resolved from target related class                                                                   |\n| `@HasMany(relatedModelGetter: () =\u003e typeof Model, foreignKey: string)`                                                        | sets `SourceModel.hasMany(RelatedModel, ...)` while `as` is key of annotated property and `foreignKey` is explicitly specified value                                                                           |\n| `@HasMany(relatedModelGetter: () =\u003e typeof Model, options: AssociationOptionsHasMany)`                                        | sets `SourceModel.hasMany(RelatedModel, ...)` while `as` is key of annotated property and `options` are additional association options                                                                         |\n| `@HasOne(relatedModelGetter: () =\u003e typeof Model)`                                                                             | sets `SourceModel.hasOne(RelatedModel, ...)` while `as` is key of annotated property and `foreignKey` is resolved from target related class                                                                    |\n| `@HasOne(relatedModelGetter: () =\u003e typeof Model, foreignKey: string)`                                                         | sets `SourceModel.hasOne(RelatedModel, ...)` while `as` is key of annotated property and `foreignKey` is explicitly specified value                                                                            |\n| `@HasOne(relatedModelGetter: () =\u003e typeof Model, options: AssociationOptionsHasOne)`                                          | sets `SourceModel.hasOne(RelatedModel, ...)` while `as` is key of annotated property and `options` are additional association options                                                                          |\n| `@BelongsToMany(relatedModelGetter: () =\u003e typeof Model, through: (() =\u003e typeof Model))`                                       | sets `SourceModel.belongsToMany(RelatedModel, {through: ThroughModel, ...})` while `as` is key of annotated property and `foreignKey`/`otherKey` is resolved from through class                                |\n| `@BelongsToMany(relatedModelGetter: () =\u003e typeof Model, through: (() =\u003e typeof Model), foreignKey: string)`                   | sets `SourceModel.belongsToMany(RelatedModel, {through: ThroughModel, ...})` while `as` is key of annotated property, `foreignKey` is explicitly specified value and `otherKey` is resolved from through class |\n| `@BelongsToMany(relatedModelGetter: () =\u003e typeof Model, through: (() =\u003e typeof Model), foreignKey: string, otherKey: string)` | sets `SourceModel.belongsToMany(RelatedModel, {through: ThroughModel, ...})` while `as` is key of annotated property and `foreignKey`/`otherKey` are explicitly specified values                               |\n| `@BelongsToMany(relatedModelGetter: () =\u003e typeof Model, through: string, foreignKey: string, otherKey: string)`               | sets `SourceModel.belongsToMany(RelatedModel, {through: throughString, ...})` while `as` is key of annotated property and `foreignKey`/`otherKey` are explicitly specified values                              |\n| `@BelongsToMany(relatedModelGetter: () =\u003e typeof Model, options: AssociationOptionsBelongsToMany)`                            | sets `SourceModel.belongsToMany(RelatedModel, {through: throughString, ...})` while `as` is key of annotated property and `options` are additional association values, including `foreignKey` and `otherKey`.  |\n\nNote that when using AssociationOptions, certain properties will be overwritten when the association is built, based on reflection metadata or explicit attribute parameters. For example, `as` will always be the annotated property's name, and `through` will be the explicitly stated value.\n\n### Multiple relations of same models\n\n_sequelize-typescript_ resolves the foreign keys by identifying the corresponding class references.\nSo if you define a model with multiple relations like\n\n```typescript\n@Table\nclass Book extends Model {\n  @ForeignKey(() =\u003e Person)\n  @Column\n  authorId: number;\n\n  @BelongsTo(() =\u003e Person)\n  author: Person;\n\n  @ForeignKey(() =\u003e Person)\n  @Column\n  proofreaderId: number;\n\n  @BelongsTo(() =\u003e Person)\n  proofreader: Person;\n}\n\n@Table\nclass Person extends Model {\n  @HasMany(() =\u003e Book)\n  writtenBooks: Book[];\n\n  @HasMany(() =\u003e Book)\n  proofedBooks: Book[];\n}\n```\n\n_sequelize-typescript_ cannot know which foreign key to use for which relation. So you have to add the foreign keys\nexplicitly:\n\n```typescript\n\n  // in class \"Books\":\n  @BelongsTo(() =\u003e Person, 'authorId')\n  author: Person;\n\n  @BelongsTo(() =\u003e Person, 'proofreaderId')\n  proofreader: Person;\n\n  // in class \"Person\":\n  @HasMany(() =\u003e Book, 'authorId')\n  writtenBooks: Book[];\n\n  @HasMany(() =\u003e Book, 'proofreaderId')\n  proofedBooks: Book[];\n```\n\n### Type safe usage of auto generated functions\n\nWith the creation of a relation, sequelize generates some method on the corresponding\nmodels. So when you create a 1:n relation between `ModelA` and `ModelB`, an instance of `ModelA` will\nhave the functions `getModelBs`, `setModelBs`, `addModelB`, `removeModelB`, `hasModelB`. These functions still exist with _sequelize-typescript_.\nBut TypeScript wont recognize them and will complain if you try to access `getModelB`, `setModelB` or\n`addModelB`. To make TypeScript happy, the `Model.prototype` of _sequelize-typescript_ has `$set`, `$get`, `$add`\nfunctions.\n\n```typescript\n@Table\nclass ModelA extends Model {\n  @HasMany(() =\u003e ModelB)\n  bs: ModelB[];\n}\n\n@Table\nclass ModelB extends Model {\n  @BelongsTo(() =\u003e ModelA)\n  a: ModelA;\n}\n```\n\nTo use them, pass the property key of the respective relation as the first parameter:\n\n```typescript\nconst modelA = new ModelA();\n\nmodelA\n  .$set('bs', [\n    /* instance */\n  ])\n  .then(/* ... */);\nmodelA.$add('b' /* instance */).then(/* ... */);\nmodelA.$get('bs').then(/* ... */);\nmodelA.$count('bs').then(/* ... */);\nmodelA.$has('bs').then(/* ... */);\nmodelA.$remove('bs' /* instance */).then(/* ... */);\nmodelA.$create('bs' /* value */).then(/* ... */);\n```\n\n## Indexes\n\n### `@Index`\n\nThe `@Index` annotation can be used without passing any parameters.\n\n```typescript\n@Table\nclass Person extends Model {\n  @Index // Define an index with default name\n  @Column\n  name: string;\n\n  @Index // Define another index\n  @Column\n  birthday: Date;\n}\n```\n\nTo specify index and index field options, use\nan object literal (see [indexes define option](https://sequelize.org/v5/manual/models-definition.html#indexes)):\n\n```typescript\n@Table\nclass Person extends Model {\n  @Index('my-index') // Define a multi-field index on name and birthday\n  @Column\n  name: string;\n\n  @Index('my-index') // Add birthday as the second field to my-index\n  @Column\n  birthday: Date;\n\n  @Index({\n    // index options\n    name: 'job-index',\n    parser: 'my-parser',\n    type: 'UNIQUE',\n    unique: true,\n    where: { isEmployee: true },\n    concurrently: true,\n    using: 'BTREE',\n    operator: 'text_pattern_ops',\n    prefix: 'test-',\n    // index field options\n    length: 10,\n    order: 'ASC',\n    collate: 'NOCASE',\n  })\n  @Column\n  jobTitle: string;\n\n  @Column\n  isEmployee: boolean;\n}\n```\n\n#### Index API\n\n| Decorator                                | Description                                                                                               |\n| ---------------------------------------- | --------------------------------------------------------------------------------------------------------- |\n| `@Index`                                 | adds new index on decorated field to `options.indexes`                                                    |\n| `@Index(name: string)`                   | adds new index or adds the field to an existing index with specified name                                 |\n| `@Table(options: IndexDecoratorOptions)` | sets both index and index field [options](https://sequelize.org/v5/manual/models-definition.html#indexes) |\n\n### `createIndexDecorator()`\n\nThe `createIndexDecorator()` function can be used to create a decorator for an index with options specified with an object literal supplied as the argument. Fields are added to the index by decorating properties.\n\n```typescript\nconst SomeIndex = createIndexDecorator();\nconst JobIndex = createIndexDecorator({\n  // index options\n  name: 'job-index',\n  parser: 'my-parser',\n  type: 'UNIQUE',\n  unique: true,\n  where: { isEmployee: true },\n  concurrently: true,\n  using: 'BTREE',\n  operator: 'text_pattern_ops',\n  prefix: 'test-',\n});\n\n@Table\nclass Person extends Model {\n  @SomeIndex // Add name to SomeIndex\n  @Column\n  name: string;\n\n  @SomeIndex // Add birthday to SomeIndex\n  @Column\n  birthday: Date;\n\n  @JobIndex({\n    // index field options\n    length: 10,\n    order: 'ASC',\n    collate: 'NOCASE',\n  })\n  @Column\n  jobTitle: string;\n\n  @Column\n  isEmployee: boolean;\n}\n```\n\n## Repository mode\n\nWith `sequelize-typescript@1` comes a repository mode. See [docs](#repository-mode) for details.\n\nThe repository mode makes it possible to separate static operations like `find`, `create`, ... from model definitions.\nIt also empowers models so that they can be used with multiple sequelize instances.\n\n### How to enable repository mode?\n\nEnable repository mode by setting `repositoryMode` flag:\n\n```typescript\nconst sequelize = new Sequelize({\n  repositoryMode: true,\n  ...,\n});\n```\n\n### How to use repository mode?\n\nRetrieve repository to create instances or perform search operations:\n\n```typescript\nconst userRepository = sequelize.getRepository(User);\n\nconst luke = await userRepository.create({ name: 'Luke Skywalker' });\nconst luke = await userRepository.findOne({ where: { name: 'luke' } });\n```\n\n### How to use associations with repository mode?\n\nFor now one need to use the repositories within the include options in order to retrieve or create related data:\n\n```typescript\nconst userRepository = sequelize.getRepository(User);\nconst addressRepository = sequelize.getRepository(Address);\n\nuserRepository.find({ include: [addressRepository] });\nuserRepository.create({ name: 'Bear' }, { include: [addressRepository] });\n```\n\n\u003e ⚠️ This will change in the future: One will be able to refer the model classes instead of the repositories.\n\n### Limitations of repository mode\n\nNested scopes and includes in general won't work when using `@Scope` annotation together with repository mode like:\n\n```typescript\n@Scopes(() =\u003e ({\n  // includes\n  withAddress: {\n    include: [() =\u003e Address],\n  },\n  // nested scopes\n  withAddressIncludingLatLng: {\n    include: [() =\u003e Address.scope('withLatLng')],\n  },\n}))\n@Table\nclass User extends Model {}\n```\n\n\u003e ⚠️ This will change in the future: Simple includes will be implemented.\n\n## Model validation\n\nValidation options can be set through the `@Column` annotation, but if you prefer to use separate decorators for\nvalidation instead, you can do so by simply adding the validate options _as_ decorators:\nSo that `validate.isEmail=true` becomes `@IsEmail`, `validate.equals='value'` becomes `@Equals('value')`\nand so on. Please notice that a validator that expects a boolean is translated to an annotation without a parameter.\n\nSee sequelize [docs](https://sequelize.org/v5/manual/models-definition.html#validations)\nfor all validators.\n\n### Exceptions\n\nThe following validators cannot simply be translated from sequelize validator to an annotation:\n\n| Validator                       | Annotation                                                                                                                                                                  |\n| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `validate.len=[number, number]` | `@Length({max?: number, min?: number})`                                                                                                                                     |\n| `validate[customName: string]`  | For custom validators also use the `@Is(...)` annotation: Either `@Is('custom', (value) =\u003e { /* ... */})` or with named function `@Is(function custom(value) { /* ... */})` |\n\n### Example\n\n```typescript\nconst HEX_REGEX = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;\n\n@Table\nexport class Shoe extends Model {\n  @IsUUID(4)\n  @PrimaryKey\n  @Column\n  id: string;\n\n  @Equals('lala')\n  @Column\n  readonly key: string;\n\n  @Contains('Special')\n  @Column\n  special: string;\n\n  @Length({ min: 3, max: 15 })\n  @Column\n  brand: string;\n\n  @IsUrl\n  @Column\n  brandUrl: string;\n\n  @Is('HexColor', (value) =\u003e {\n    if (!HEX_REGEX.test(value)) {\n      throw new Error(`\"${value}\" is not a hex color value.`);\n    }\n  })\n  @Column\n  primaryColor: string;\n\n  @Is(function hexColor(value: string): void {\n    if (!HEX_REGEX.test(value)) {\n      throw new Error(`\"${value}\" is not a hex color value.`);\n    }\n  })\n  @Column\n  secondaryColor: string;\n\n  @Is(HEX_REGEX)\n  @Column\n  tertiaryColor: string;\n\n  @IsDate\n  @IsBefore('2017-02-27')\n  @Column\n  producedAt: Date;\n}\n```\n\n## Scopes\n\nScopes can be defined with annotations as well. The scope options are identical to native\nsequelize (See sequelize [docs](https://sequelize.org/master/manual/scopes.html) for more details)\n\n### `@DefaultScope` and `@Scopes`\n\n```typescript\n@DefaultScope(() =\u003e ({\n  attributes: ['id', 'primaryColor', 'secondaryColor', 'producedAt'],\n}))\n@Scopes(() =\u003e ({\n  full: {\n    include: [Manufacturer],\n  },\n  yellow: {\n    where: { primaryColor: 'yellow' },\n  },\n}))\n@Table\nexport class ShoeWithScopes extends Model {\n  @Column\n  readonly secretKey: string;\n\n  @Column\n  primaryColor: string;\n\n  @Column\n  secondaryColor: string;\n\n  @Column\n  producedAt: Date;\n\n  @ForeignKey(() =\u003e Manufacturer)\n  @Column\n  manufacturerId: number;\n\n  @BelongsTo(() =\u003e Manufacturer)\n  manufacturer: Manufacturer;\n}\n```\n\n## Hooks\n\nHooks can be attached to your models. All Model-level hooks are supported. See [the related unit tests](test/models/Hook.ts) for a summary.\n\nEach hook must be a `static` method. Multiple hooks can be attached to a single method, and you can define multiple methods for a given hook.\n\nThe name of the method cannot be the same as the name of the hook (for example, a `@BeforeCreate` hook method cannot be named `beforeCreate`). That’s because Sequelize has pre-defined methods with those names.\n\n```typescript\n@Table\nexport class Person extends Model {\n  @Column\n  name: string;\n\n  @BeforeUpdate\n  @BeforeCreate\n  static makeUpperCase(instance: Person) {\n    // this will be called when an instance is created or updated\n    instance.name = instance.name.toLocaleUpperCase();\n  }\n\n  @BeforeCreate\n  static addUnicorn(instance: Person) {\n    // this will also be called when an instance is created\n    instance.name += ' 🦄';\n  }\n}\n```\n\n## Why `() =\u003e Model`?\n\n`@ForeignKey(Model)` is much easier to read, so why is `@ForeignKey(() =\u003e Model)` so important? When it\ncomes to circular-dependencies (which are in general solved by node for you) `Model` can be `undefined`\nwhen it gets passed to @ForeignKey. With the usage of a function, which returns the actual model, we prevent\nthis issue.\n\n## Recommendations and limitations\n\n### One Sequelize instance per model (without repository mode)\n\nUnless you are using the [repository mode](#repository-mode), you won't be able to add one and the same model to multiple\nSequelize instances with differently configured connections. So that one model will only work for one connection.\n\n### One model class per file\n\nThis is not only good practice regarding design, but also matters for the order\nof execution. Since Typescript creates a `__metadata(\"design:type\", SomeModel)` call due to `emitDecoratorMetadata`\ncompile option, in some cases `SomeModel` is probably not defined(not undefined!) and would throw a `ReferenceError`.\nWhen putting `SomeModel` in a separate file, it would look like `__metadata(\"design:type\", SomeModel_1.SomeModel)`,\nwhich does not throw an error.\n\n### Minification\n\nIf you need to minify your code, you need to set `tableName` and `modelName`\nin the `DefineOptions` for `@Table` annotation. sequelize-typescript\nuses the class name as default name for `tableName` and `modelName`.\nWhen the code is minified the class name will no longer be the originally\ndefined one (So that `class User` will become `class b` for example).\n\n## Contributing\n\nTo contribute you can:\n\n- Open issues and participate in discussion of other issues.\n- Fork the project to open up PR's.\n- Update the [types of Sequelize](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/sequelize).\n- Anything else constructively helpful.\n\nIn order to open a pull request please:\n\n- Create a new branch.\n- Run tests locally (`npm install \u0026\u0026 npm run build \u0026\u0026 npm run cover`) and ensure your commits don't break the tests.\n- Document your work well with commit messages, a good PR description, comments in code when necessary, etc.\n\nIn order to update the types for sequelize please go to [the Definitely Typed repo](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/sequelize), it would also be a good\nidea to open a PR into [sequelize](https://github.com/sequelize/sequelize) so that Sequelize can maintain its own types, but that\nmight be harder than getting updated types into microsoft's repo. The Typescript team is slowly trying to encourage\nnpm package maintainers to maintain their own typings, but Microsoft still has dedicated and good people maintaining the DT repo,\naccepting PR's and keeping quality high.\n\n**Keep in mind `sequelize-typescript` does not provide typings for `sequelize`** - these are seperate things.\nA lot of the types in `sequelize-typescript` augment, refer to, or extend what sequelize already has.\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsequelize%2Fsequelize-typescript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsequelize%2Fsequelize-typescript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsequelize%2Fsequelize-typescript/lists"}