不要怂,就是干,撸起袖子干!

Commit 871157bc by Harry Yu Committed by GitHub

feat(types): added optional stricter typing for Model attributes (#12405)

1 parent e36212c8
...@@ -19,7 +19,21 @@ Example of a minimal TypeScript project: ...@@ -19,7 +19,21 @@ Example of a minimal TypeScript project:
import { Sequelize, Model, DataTypes, BuildOptions } from 'sequelize'; import { Sequelize, Model, DataTypes, BuildOptions } from 'sequelize';
import { HasManyGetAssociationsMixin, HasManyAddAssociationMixin, HasManyHasAssociationMixin, Association, HasManyCountAssociationsMixin, HasManyCreateAssociationMixin } from 'sequelize'; import { HasManyGetAssociationsMixin, HasManyAddAssociationMixin, HasManyHasAssociationMixin, Association, HasManyCountAssociationsMixin, HasManyCreateAssociationMixin } from 'sequelize';
class User extends Model { // These are the minimum attributes needed to create a User
interface UserCreationAttributes {
name: string;
preferredName: string | null;
}
// These are all the attributes in the User model
interface UserAttributes extends UserCreationAttributes {
id: number;
}
// You can choose to omit the `UserAttributes` and `UserCreationAttributes`
// generic types to simplify your types. This will come at the cost of making
// typechecking slightly less strict.
class User extends Model<UserAttributes, UserCreationAttributes> implements UserAttributes {
public id!: number; // Note that the `null assertion` `!` is required in strict mode. public id!: number; // Note that the `null assertion` `!` is required in strict mode.
public name!: string; public name!: string;
public preferredName!: string | null; // for nullable fields public preferredName!: string | null; // for nullable fields
...@@ -49,7 +63,16 @@ class User extends Model { ...@@ -49,7 +63,16 @@ class User extends Model {
const sequelize = new Sequelize('mysql://root:asd123@localhost:3306/mydb'); const sequelize = new Sequelize('mysql://root:asd123@localhost:3306/mydb');
class Project extends Model { interface ProjectAttributes {
ownerId: number;
name: string;
}
interface ProjectAttributes extends ProjectCreationAttributes {
id: number;
}
class Project extends Model<ProjectAttributes, ProjectCreationAttributes> implements ProjectAttributes {
public id!: number; public id!: number;
public ownerId!: number; public ownerId!: number;
public name!: string; public name!: string;
...@@ -58,7 +81,12 @@ class Project extends Model { ...@@ -58,7 +81,12 @@ class Project extends Model {
public readonly updatedAt!: Date; public readonly updatedAt!: Date;
} }
class Address extends Model { interface AddressAttributes {
userId: number;
address: string;
}
class Address extends Model<AddressAttributes> implements AddressAttributes {
public userId!: number; public userId!: number;
public address!: string; public address!: string;
...@@ -149,21 +177,45 @@ async function stuff() { ...@@ -149,21 +177,45 @@ async function stuff() {
## Usage of `sequelize.define` ## Usage of `sequelize.define`
TypeScript doesn't know how to generate a `class` definition when we use the `sequelize.define` method to define a Model. Therefore, we need to do some manual work and declare an interface and a type, and eventually cast the result of `.define` to the _static_ type. In Sequelize versions before v5, the default way of defining a model involved using `sequelize.define`. It's still possible to define models with that, and you can also add typings to these models using interfaces.
```ts ```ts
// We need to declare an interface for our model that is basically what our class would be // We recommend you declare an interface for the attributes, for stricter typechecking
interface MyModel extends Model { interface MyModelAttributes {
readonly id: number; readonly id: number;
name: string;
}
interface MyModelCreationAttributes extends Optional<MyModelAttributes, 'id'> {}
// We need to declare an interface for our model that is basically what our class would be
interface MyModel extends Model<MyModelAttributes, MyModelCreationAttributes>, MyModelAttributes {}
const MyDefineModel = sequelize.define<MyModel>('MyDefineModel', {
id: {
primaryKey: true,
type: DataTypes.INTEGER.UNSIGNED,
}
});
async function stuffTwo() {
const myModel = await MyDefineModel.findByPk(1, {
rejectOnEmpty: true,
});
console.log(myModel.id);
} }
```
If you're comfortable with somewhat less strict typing for the attributes on a model, you can save some code by defining the Instance to just extend `Model` without any attributes in the generic types.
// Need to declare the static model so `findOne` etc. use correct types. ```ts
type MyModelStatic = typeof Model & { // We need to declare an interface for our model that is basically what our class would be
new (values?: object, options?: BuildOptions): MyModel; interface MyModel extends Model {
readonly id: number;
name: string;
} }
// TS can't derive a proper class definition from a `.define` call, therefor we need to cast here. const MyDefineModel = sequelize.define<MyModel>('MyDefineModel', {
const MyDefineModel = <MyModelStatic>sequelize.define('MyDefineModel', {
id: { id: {
primaryKey: true, primaryKey: true,
type: DataTypes.INTEGER.UNSIGNED, type: DataTypes.INTEGER.UNSIGNED,
......
...@@ -17,3 +17,9 @@ export { BaseError as Error } from './lib/errors'; ...@@ -17,3 +17,9 @@ export { BaseError as Error } from './lib/errors';
export { useInflection } from './lib/utils'; export { useInflection } from './lib/utils';
export { Utils, QueryTypes, Op, TableHints, IndexHints, DataTypes, Deferrable }; export { Utils, QueryTypes, Op, TableHints, IndexHints, DataTypes, Deferrable };
export { Validator as validator } from './lib/utils/validator-extras'; export { Validator as validator } from './lib/utils/validator-extras';
/**
* Type helper for making certain fields of an object optional. This is helpful
* for creating the `CreationAttributes` from your `Attributes` for a Model.
*/
export type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
...@@ -104,7 +104,7 @@ export class BelongsToMany<S extends Model = Model, T extends Model = Model> ext ...@@ -104,7 +104,7 @@ export class BelongsToMany<S extends Model = Model, T extends Model = Model> ext
* The options for the getAssociations mixin of the belongsToMany association. * The options for the getAssociations mixin of the belongsToMany association.
* @see BelongsToManyGetAssociationsMixin * @see BelongsToManyGetAssociationsMixin
*/ */
export interface BelongsToManyGetAssociationsMixinOptions extends FindOptions { export interface BelongsToManyGetAssociationsMixinOptions extends FindOptions<any> {
/** /**
* A list of the attributes from the join table that you want to select. * A list of the attributes from the join table that you want to select.
*/ */
...@@ -149,9 +149,9 @@ export type BelongsToManyGetAssociationsMixin<TModel> = ( ...@@ -149,9 +149,9 @@ export type BelongsToManyGetAssociationsMixin<TModel> = (
* @see BelongsToManySetAssociationsMixin * @see BelongsToManySetAssociationsMixin
*/ */
export interface BelongsToManySetAssociationsMixinOptions export interface BelongsToManySetAssociationsMixinOptions
extends FindOptions, extends FindOptions<any>,
BulkCreateOptions, BulkCreateOptions<any>,
InstanceUpdateOptions, InstanceUpdateOptions<any>,
InstanceDestroyOptions { InstanceDestroyOptions {
through?: JoinTableAttributes; through?: JoinTableAttributes;
} }
...@@ -191,9 +191,9 @@ export type BelongsToManySetAssociationsMixin<TModel, TModelPrimaryKey> = ( ...@@ -191,9 +191,9 @@ export type BelongsToManySetAssociationsMixin<TModel, TModelPrimaryKey> = (
* @see BelongsToManyAddAssociationsMixin * @see BelongsToManyAddAssociationsMixin
*/ */
export interface BelongsToManyAddAssociationsMixinOptions export interface BelongsToManyAddAssociationsMixinOptions
extends FindOptions, extends FindOptions<any>,
BulkCreateOptions, BulkCreateOptions<any>,
InstanceUpdateOptions, InstanceUpdateOptions<any>,
InstanceDestroyOptions { InstanceDestroyOptions {
through?: JoinTableAttributes; through?: JoinTableAttributes;
} }
...@@ -233,9 +233,9 @@ export type BelongsToManyAddAssociationsMixin<TModel, TModelPrimaryKey> = ( ...@@ -233,9 +233,9 @@ export type BelongsToManyAddAssociationsMixin<TModel, TModelPrimaryKey> = (
* @see BelongsToManyAddAssociationMixin * @see BelongsToManyAddAssociationMixin
*/ */
export interface BelongsToManyAddAssociationMixinOptions export interface BelongsToManyAddAssociationMixinOptions
extends FindOptions, extends FindOptions<any>,
BulkCreateOptions, BulkCreateOptions<any>,
InstanceUpdateOptions, InstanceUpdateOptions<any>,
InstanceDestroyOptions { InstanceDestroyOptions {
through?: JoinTableAttributes; through?: JoinTableAttributes;
} }
...@@ -274,7 +274,7 @@ export type BelongsToManyAddAssociationMixin<TModel, TModelPrimaryKey> = ( ...@@ -274,7 +274,7 @@ export type BelongsToManyAddAssociationMixin<TModel, TModelPrimaryKey> = (
* The options for the createAssociation mixin of the belongsToMany association. * The options for the createAssociation mixin of the belongsToMany association.
* @see BelongsToManyCreateAssociationMixin * @see BelongsToManyCreateAssociationMixin
*/ */
export interface BelongsToManyCreateAssociationMixinOptions extends CreateOptions { export interface BelongsToManyCreateAssociationMixinOptions extends CreateOptions<any> {
through?: JoinTableAttributes; through?: JoinTableAttributes;
} }
/** /**
...@@ -455,7 +455,7 @@ export type BelongsToManyHasAssociationsMixin<TModel, TModelPrimaryKey> = ( ...@@ -455,7 +455,7 @@ export type BelongsToManyHasAssociationsMixin<TModel, TModelPrimaryKey> = (
* The options for the countAssociations mixin of the belongsToMany association. * The options for the countAssociations mixin of the belongsToMany association.
* @see BelongsToManyCountAssociationsMixin * @see BelongsToManyCountAssociationsMixin
*/ */
export interface BelongsToManyCountAssociationsMixinOptions extends Transactionable, Filterable { export interface BelongsToManyCountAssociationsMixinOptions extends Transactionable, Filterable<any> {
/** /**
* Apply a scope on the related model, or remove its default scope by passing false. * Apply a scope on the related model, or remove its default scope by passing false.
*/ */
......
...@@ -30,7 +30,7 @@ export class BelongsTo<S extends Model = Model, T extends Model = Model> extends ...@@ -30,7 +30,7 @@ export class BelongsTo<S extends Model = Model, T extends Model = Model> extends
* The options for the getAssociation mixin of the belongsTo association. * The options for the getAssociation mixin of the belongsTo association.
* @see BelongsToGetAssociationMixin * @see BelongsToGetAssociationMixin
*/ */
export interface BelongsToGetAssociationMixinOptions extends FindOptions { export interface BelongsToGetAssociationMixinOptions extends FindOptions<any> {
/** /**
* Apply a scope on the related model, or remove its default scope by passing false. * Apply a scope on the related model, or remove its default scope by passing false.
*/ */
...@@ -61,7 +61,7 @@ export type BelongsToGetAssociationMixin<TModel> = (options?: BelongsToGetAssoci ...@@ -61,7 +61,7 @@ export type BelongsToGetAssociationMixin<TModel> = (options?: BelongsToGetAssoci
* The options for the setAssociation mixin of the belongsTo association. * The options for the setAssociation mixin of the belongsTo association.
* @see BelongsToSetAssociationMixin * @see BelongsToSetAssociationMixin
*/ */
export interface BelongsToSetAssociationMixinOptions extends SaveOptions { export interface BelongsToSetAssociationMixinOptions extends SaveOptions<any> {
/** /**
* Skip saving this after setting the foreign key if false. * Skip saving this after setting the foreign key if false.
*/ */
...@@ -95,7 +95,8 @@ export type BelongsToSetAssociationMixin<TModel, TPrimaryKey> = ( ...@@ -95,7 +95,8 @@ export type BelongsToSetAssociationMixin<TModel, TPrimaryKey> = (
* The options for the createAssociation mixin of the belongsTo association. * The options for the createAssociation mixin of the belongsTo association.
* @see BelongsToCreateAssociationMixin * @see BelongsToCreateAssociationMixin
*/ */
export interface BelongsToCreateAssociationMixinOptions extends CreateOptions, BelongsToSetAssociationMixinOptions {} export interface BelongsToCreateAssociationMixinOptions
extends CreateOptions<any>, BelongsToSetAssociationMixinOptions {}
/** /**
* The createAssociation mixin applied to models with belongsTo. * The createAssociation mixin applied to models with belongsTo.
......
...@@ -36,7 +36,7 @@ export class HasMany<S extends Model = Model, T extends Model = Model> extends A ...@@ -36,7 +36,7 @@ export class HasMany<S extends Model = Model, T extends Model = Model> extends A
* The options for the getAssociations mixin of the hasMany association. * The options for the getAssociations mixin of the hasMany association.
* @see HasManyGetAssociationsMixin * @see HasManyGetAssociationsMixin
*/ */
export interface HasManyGetAssociationsMixinOptions extends FindOptions { export interface HasManyGetAssociationsMixinOptions extends FindOptions<any> {
/** /**
* Apply a scope on the related model, or remove its default scope by passing false. * Apply a scope on the related model, or remove its default scope by passing false.
*/ */
...@@ -74,7 +74,7 @@ export type HasManyGetAssociationsMixin<TModel> = (options?: HasManyGetAssociati ...@@ -74,7 +74,7 @@ export type HasManyGetAssociationsMixin<TModel> = (options?: HasManyGetAssociati
* The options for the setAssociations mixin of the hasMany association. * The options for the setAssociations mixin of the hasMany association.
* @see HasManySetAssociationsMixin * @see HasManySetAssociationsMixin
*/ */
export interface HasManySetAssociationsMixinOptions extends FindOptions, InstanceUpdateOptions {} export interface HasManySetAssociationsMixinOptions extends FindOptions<any>, InstanceUpdateOptions<any> {}
/** /**
* The setAssociations mixin applied to models with hasMany. * The setAssociations mixin applied to models with hasMany.
...@@ -110,7 +110,7 @@ export type HasManySetAssociationsMixin<TModel, TModelPrimaryKey> = ( ...@@ -110,7 +110,7 @@ export type HasManySetAssociationsMixin<TModel, TModelPrimaryKey> = (
* The options for the addAssociations mixin of the hasMany association. * The options for the addAssociations mixin of the hasMany association.
* @see HasManyAddAssociationsMixin * @see HasManyAddAssociationsMixin
*/ */
export interface HasManyAddAssociationsMixinOptions extends InstanceUpdateOptions {} export interface HasManyAddAssociationsMixinOptions extends InstanceUpdateOptions<any> {}
/** /**
* The addAssociations mixin applied to models with hasMany. * The addAssociations mixin applied to models with hasMany.
...@@ -146,7 +146,7 @@ export type HasManyAddAssociationsMixin<TModel, TModelPrimaryKey> = ( ...@@ -146,7 +146,7 @@ export type HasManyAddAssociationsMixin<TModel, TModelPrimaryKey> = (
* The options for the addAssociation mixin of the hasMany association. * The options for the addAssociation mixin of the hasMany association.
* @see HasManyAddAssociationMixin * @see HasManyAddAssociationMixin
*/ */
export interface HasManyAddAssociationMixinOptions extends InstanceUpdateOptions {} export interface HasManyAddAssociationMixinOptions extends InstanceUpdateOptions<any> {}
/** /**
* The addAssociation mixin applied to models with hasMany. * The addAssociation mixin applied to models with hasMany.
...@@ -182,7 +182,7 @@ export type HasManyAddAssociationMixin<TModel, TModelPrimaryKey> = ( ...@@ -182,7 +182,7 @@ export type HasManyAddAssociationMixin<TModel, TModelPrimaryKey> = (
* The options for the createAssociation mixin of the hasMany association. * The options for the createAssociation mixin of the hasMany association.
* @see HasManyCreateAssociationMixin * @see HasManyCreateAssociationMixin
*/ */
export interface HasManyCreateAssociationMixinOptions extends CreateOptions {} export interface HasManyCreateAssociationMixinOptions extends CreateOptions<any> {}
/** /**
* The createAssociation mixin applied to models with hasMany. * The createAssociation mixin applied to models with hasMany.
...@@ -218,7 +218,7 @@ export type HasManyCreateAssociationMixin<TModel> = ( ...@@ -218,7 +218,7 @@ export type HasManyCreateAssociationMixin<TModel> = (
* The options for the removeAssociation mixin of the hasMany association. * The options for the removeAssociation mixin of the hasMany association.
* @see HasManyRemoveAssociationMixin * @see HasManyRemoveAssociationMixin
*/ */
export interface HasManyRemoveAssociationMixinOptions extends InstanceUpdateOptions {} export interface HasManyRemoveAssociationMixinOptions extends InstanceUpdateOptions<any> {}
/** /**
* The removeAssociation mixin applied to models with hasMany. * The removeAssociation mixin applied to models with hasMany.
...@@ -254,7 +254,7 @@ export type HasManyRemoveAssociationMixin<TModel, TModelPrimaryKey> = ( ...@@ -254,7 +254,7 @@ export type HasManyRemoveAssociationMixin<TModel, TModelPrimaryKey> = (
* The options for the removeAssociations mixin of the hasMany association. * The options for the removeAssociations mixin of the hasMany association.
* @see HasManyRemoveAssociationsMixin * @see HasManyRemoveAssociationsMixin
*/ */
export interface HasManyRemoveAssociationsMixinOptions extends InstanceUpdateOptions {} export interface HasManyRemoveAssociationsMixinOptions extends InstanceUpdateOptions<any> {}
/** /**
* The removeAssociations mixin applied to models with hasMany. * The removeAssociations mixin applied to models with hasMany.
...@@ -362,7 +362,7 @@ export type HasManyHasAssociationsMixin<TModel, TModelPrimaryKey> = ( ...@@ -362,7 +362,7 @@ export type HasManyHasAssociationsMixin<TModel, TModelPrimaryKey> = (
* The options for the countAssociations mixin of the hasMany association. * The options for the countAssociations mixin of the hasMany association.
* @see HasManyCountAssociationsMixin * @see HasManyCountAssociationsMixin
*/ */
export interface HasManyCountAssociationsMixinOptions extends Transactionable, Filterable { export interface HasManyCountAssociationsMixinOptions extends Transactionable, Filterable<any> {
/** /**
* Apply a scope on the related model, or remove its default scope by passing false. * Apply a scope on the related model, or remove its default scope by passing false.
*/ */
......
...@@ -28,7 +28,7 @@ export class HasOne<S extends Model = Model, T extends Model = Model> extends As ...@@ -28,7 +28,7 @@ export class HasOne<S extends Model = Model, T extends Model = Model> extends As
* The options for the getAssociation mixin of the hasOne association. * The options for the getAssociation mixin of the hasOne association.
* @see HasOneGetAssociationMixin * @see HasOneGetAssociationMixin
*/ */
export interface HasOneGetAssociationMixinOptions extends FindOptions { export interface HasOneGetAssociationMixinOptions extends FindOptions<any> {
/** /**
* Apply a scope on the related model, or remove its default scope by passing false. * Apply a scope on the related model, or remove its default scope by passing false.
*/ */
...@@ -59,7 +59,7 @@ export type HasOneGetAssociationMixin<TModel> = (options?: HasOneGetAssociationM ...@@ -59,7 +59,7 @@ export type HasOneGetAssociationMixin<TModel> = (options?: HasOneGetAssociationM
* The options for the setAssociation mixin of the hasOne association. * The options for the setAssociation mixin of the hasOne association.
* @see HasOneSetAssociationMixin * @see HasOneSetAssociationMixin
*/ */
export interface HasOneSetAssociationMixinOptions extends HasOneGetAssociationMixinOptions, SaveOptions { export interface HasOneSetAssociationMixinOptions extends HasOneGetAssociationMixinOptions, SaveOptions<any> {
/** /**
* Skip saving this after setting the foreign key if false. * Skip saving this after setting the foreign key if false.
*/ */
...@@ -93,7 +93,7 @@ export type HasOneSetAssociationMixin<TModel, TModelPrimaryKey> = ( ...@@ -93,7 +93,7 @@ export type HasOneSetAssociationMixin<TModel, TModelPrimaryKey> = (
* The options for the createAssociation mixin of the hasOne association. * The options for the createAssociation mixin of the hasOne association.
* @see HasOneCreateAssociationMixin * @see HasOneCreateAssociationMixin
*/ */
export interface HasOneCreateAssociationMixinOptions extends HasOneSetAssociationMixinOptions, CreateOptions {} export interface HasOneCreateAssociationMixinOptions extends HasOneSetAssociationMixinOptions, CreateOptions<any> {}
/** /**
* The createAssociation mixin applied to models with hasOne. * The createAssociation mixin applied to models with hasOne.
......
...@@ -21,40 +21,50 @@ export type HookReturn = Promise<void> | void; ...@@ -21,40 +21,50 @@ export type HookReturn = Promise<void> | void;
* Options for Model.init. We mostly duplicate the Hooks here, since there is no way to combine the two * Options for Model.init. We mostly duplicate the Hooks here, since there is no way to combine the two
* interfaces. * interfaces.
*/ */
export interface ModelHooks<M extends Model = Model> { export interface ModelHooks<M extends Model = Model, TAttributes = any> {
beforeValidate(instance: M, options: ValidationOptions): HookReturn; beforeValidate(instance: M, options: ValidationOptions): HookReturn;
afterValidate(instance: M, options: ValidationOptions): HookReturn; afterValidate(instance: M, options: ValidationOptions): HookReturn;
beforeCreate(attributes: M, options: CreateOptions): HookReturn; beforeCreate(attributes: M, options: CreateOptions<TAttributes>): HookReturn;
afterCreate(attributes: M, options: CreateOptions): HookReturn; afterCreate(attributes: M, options: CreateOptions<TAttributes>): HookReturn;
beforeDestroy(instance: M, options: InstanceDestroyOptions): HookReturn; beforeDestroy(instance: M, options: InstanceDestroyOptions): HookReturn;
afterDestroy(instance: M, options: InstanceDestroyOptions): HookReturn; afterDestroy(instance: M, options: InstanceDestroyOptions): HookReturn;
beforeRestore(instance: M, options: InstanceRestoreOptions): HookReturn; beforeRestore(instance: M, options: InstanceRestoreOptions): HookReturn;
afterRestore(instance: M, options: InstanceRestoreOptions): HookReturn; afterRestore(instance: M, options: InstanceRestoreOptions): HookReturn;
beforeUpdate(instance: M, options: InstanceUpdateOptions): HookReturn; beforeUpdate(instance: M, options: InstanceUpdateOptions<TAttributes>): HookReturn;
afterUpdate(instance: M, options: InstanceUpdateOptions): HookReturn; afterUpdate(instance: M, options: InstanceUpdateOptions<TAttributes>): HookReturn;
beforeSave(instance: M, options: InstanceUpdateOptions | CreateOptions): HookReturn; beforeSave(
afterSave(instance: M, options: InstanceUpdateOptions | CreateOptions): HookReturn; instance: M,
beforeBulkCreate(instances: M[], options: BulkCreateOptions): HookReturn; options: InstanceUpdateOptions<TAttributes> | CreateOptions<TAttributes>
afterBulkCreate(instances: M[], options: BulkCreateOptions): HookReturn; ): HookReturn;
beforeBulkDestroy(options: DestroyOptions): HookReturn; afterSave(
afterBulkDestroy(options: DestroyOptions): HookReturn; instance: M,
beforeBulkRestore(options: RestoreOptions): HookReturn; options: InstanceUpdateOptions<TAttributes> | CreateOptions<TAttributes>
afterBulkRestore(options: RestoreOptions): HookReturn; ): HookReturn;
beforeBulkUpdate(options: UpdateOptions): HookReturn; beforeBulkCreate(instances: M[], options: BulkCreateOptions<TAttributes>): HookReturn;
afterBulkUpdate(options: UpdateOptions): HookReturn; afterBulkCreate(instances: M[], options: BulkCreateOptions<TAttributes>): HookReturn;
beforeFind(options: FindOptions): HookReturn; beforeBulkDestroy(options: DestroyOptions<TAttributes>): HookReturn;
beforeCount(options: CountOptions): HookReturn; afterBulkDestroy(options: DestroyOptions<TAttributes>): HookReturn;
beforeFindAfterExpandIncludeAll(options: FindOptions): HookReturn; beforeBulkRestore(options: RestoreOptions<TAttributes>): HookReturn;
beforeFindAfterOptions(options: FindOptions): HookReturn; afterBulkRestore(options: RestoreOptions<TAttributes>): HookReturn;
afterFind(instancesOrInstance: M[] | M | null, options: FindOptions): HookReturn; beforeBulkUpdate(options: UpdateOptions<TAttributes>): HookReturn;
afterBulkUpdate(options: UpdateOptions<TAttributes>): HookReturn;
beforeFind(options: FindOptions<TAttributes>): HookReturn;
beforeCount(options: CountOptions<TAttributes>): HookReturn;
beforeFindAfterExpandIncludeAll(options: FindOptions<TAttributes>): HookReturn;
beforeFindAfterOptions(options: FindOptions<TAttributes>): HookReturn;
afterFind(instancesOrInstance: M[] | M | null, options: FindOptions<TAttributes>): HookReturn;
beforeSync(options: SyncOptions): HookReturn; beforeSync(options: SyncOptions): HookReturn;
afterSync(options: SyncOptions): HookReturn; afterSync(options: SyncOptions): HookReturn;
beforeBulkSync(options: SyncOptions): HookReturn; beforeBulkSync(options: SyncOptions): HookReturn;
afterBulkSync(options: SyncOptions): HookReturn; afterBulkSync(options: SyncOptions): HookReturn;
} }
export interface SequelizeHooks extends ModelHooks { export interface SequelizeHooks<
beforeDefine(attributes: ModelAttributes, options: ModelOptions<Model>): void; M extends Model<TAttributes, TCreationAttributes> = Model,
TAttributes = any,
TCreationAttributes = TAttributes
> extends ModelHooks<M, TAttributes> {
beforeDefine(attributes: ModelAttributes<M, TCreationAttributes>, options: ModelOptions<M>): void;
afterDefine(model: typeof Model): void; afterDefine(model: typeof Model): void;
beforeInit(config: Config, options: Options): void; beforeInit(config: Config, options: Options): void;
afterInit(sequelize: Sequelize): void; afterInit(sequelize: Sequelize): void;
...@@ -67,33 +77,72 @@ export interface SequelizeHooks extends ModelHooks { ...@@ -67,33 +77,72 @@ export interface SequelizeHooks extends ModelHooks {
/** /**
* Virtual class for deduplication * Virtual class for deduplication
*/ */
export class Hooks { export class Hooks<
M extends Model<TModelAttributes, TCreationAttributes> = Model,
TModelAttributes extends {} = any,
TCreationAttributes extends {} = TModelAttributes
> {
/**
* A dummy variable that doesn't exist on the real object. This exists so
* Typescript can infer the type of the attributes in static functions. Don't
* try to access this!
*/
_model: M;
/**
* A similar dummy variable that doesn't exist on the real object. Do not
* try to access this in real code.
*/
_attributes: TModelAttributes;
/**
* A similar dummy variable that doesn't exist on the real object. Do not
* try to access this in real code.
*/
_creationAttributes: TCreationAttributes;
/** /**
* Add a hook to the model * Add a hook to the model
* *
* @param name Provide a name for the hook function. It can be used to remove the hook later or to order * @param name Provide a name for the hook function. It can be used to remove the hook later or to order
* hooks based on some sort of priority system in the future. * hooks based on some sort of priority system in the future.
*/ */
public static addHook<C extends typeof Hooks, K extends keyof SequelizeHooks>( public static addHook<
H extends Hooks,
K extends keyof SequelizeHooks<H['_model'], H['_attributes'], H['_creationAttributes']>
>(
this: HooksStatic<H>,
hookType: K, hookType: K,
name: string, name: string,
fn: SequelizeHooks[K] fn: SequelizeHooks<H['_model'], H['_attributes'], H['_creationAttributes']>[K]
): C; ): HooksCtor<H>;
public static addHook<C extends typeof Hooks, K extends keyof SequelizeHooks>( public static addHook<
H extends Hooks,
K extends keyof SequelizeHooks<H['_model'], H['_attributes'], H['_creationAttributes']>
>(
this: HooksStatic<H>,
hookType: K, hookType: K,
fn: SequelizeHooks[K] fn: SequelizeHooks<H['_model'], H['_attributes'], H['_creationAttributes']>[K]
): C; ): HooksCtor<H>;
/** /**
* Remove hook from the model * Remove hook from the model
*/ */
public static removeHook<C extends typeof Hooks, K extends keyof SequelizeHooks>(hookType: K, name: string): C; public static removeHook<H extends Hooks>(
this: HooksStatic<H>,
hookType: keyof SequelizeHooks<H['_model'], H['_attributes'], H['_creationAttributes']>,
name: string,
): HooksCtor<H>;
/** /**
* Check whether the mode has any hooks of this type * Check whether the mode has any hooks of this type
*/ */
public static hasHook<K extends keyof SequelizeHooks>(hookType: K): boolean; public static hasHook<H extends Hooks>(
public static hasHooks<K extends keyof SequelizeHooks>(hookType: K): boolean; this: HooksStatic<H>,
hookType: keyof SequelizeHooks<H['_model'], H['_attributes'], H['_creationAttributes']>,
): boolean;
public static hasHooks<H extends Hooks>(
this: HooksStatic<H>,
hookType: keyof SequelizeHooks<H['_model'], H['_attributes'], H['_creationAttributes']>,
): boolean;
/** /**
* Add a hook to the model * Add a hook to the model
...@@ -101,16 +150,28 @@ export class Hooks { ...@@ -101,16 +150,28 @@ export class Hooks {
* @param name Provide a name for the hook function. It can be used to remove the hook later or to order * @param name Provide a name for the hook function. It can be used to remove the hook later or to order
* hooks based on some sort of priority system in the future. * hooks based on some sort of priority system in the future.
*/ */
public addHook<K extends keyof SequelizeHooks>(hookType: K, name: string, fn: SequelizeHooks[K]): this; public addHook<K extends keyof SequelizeHooks<M, TModelAttributes, TCreationAttributes>>(
public addHook<K extends keyof SequelizeHooks>(hookType: K, fn: SequelizeHooks[K]): this; hookType: K,
name: string,
fn: SequelizeHooks<Model, TModelAttributes, TCreationAttributes>[K]
): this;
public addHook<K extends keyof SequelizeHooks<M, TModelAttributes, TCreationAttributes>>(
hookType: K, fn: SequelizeHooks<M, TModelAttributes, TCreationAttributes>[K]): this;
/** /**
* Remove hook from the model * Remove hook from the model
*/ */
public removeHook<K extends keyof SequelizeHooks>(hookType: K, name: string): this; public removeHook<K extends keyof SequelizeHooks<M, TModelAttributes, TCreationAttributes>>(
hookType: K,
name: string
): this;
/** /**
* Check whether the mode has any hooks of this type * Check whether the mode has any hooks of this type
*/ */
public hasHook<K extends keyof SequelizeHooks>(hookType: K): boolean; public hasHook<K extends keyof SequelizeHooks<M, TModelAttributes, TCreationAttributes>>(hookType: K): boolean;
public hasHooks<K extends keyof SequelizeHooks>(hookType: K): boolean; public hasHooks<K extends keyof SequelizeHooks<M, TModelAttributes, TCreationAttributes>>(hookType: K): boolean;
} }
export type HooksCtor<H extends Hooks> = typeof Hooks & { new(): H };
export type HooksStatic<H extends Hooks> = { new(): H };
...@@ -45,11 +45,11 @@ export interface SearchPathable { ...@@ -45,11 +45,11 @@ export interface SearchPathable {
searchPath?: string; searchPath?: string;
} }
export interface Filterable { export interface Filterable<TAttributes = any> {
/** /**
* Attribute has to be matched for rows to be selected for the given action. * Attribute has to be matched for rows to be selected for the given action.
*/ */
where?: WhereOptions; where?: WhereOptions<TAttributes>;
} }
export interface Projectable { export interface Projectable {
...@@ -109,7 +109,13 @@ export interface ScopeOptions { ...@@ -109,7 +109,13 @@ export interface ScopeOptions {
/** /**
* The type accepted by every `where` option * The type accepted by every `where` option
*/ */
export type WhereOptions = WhereAttributeHash | AndOperator | OrOperator | Literal | Fn | Where; export type WhereOptions<TAttributes = any> =
| WhereAttributeHash<TAttributes>
| AndOperator<TAttributes>
| OrOperator<TAttributes>
| Literal
| Fn
| Where;
/** /**
* Example: `[Op.any]: [2,3]` becomes `ANY ARRAY[2, 3]::INTEGER` * Example: `[Op.any]: [2,3]` becomes `ANY ARRAY[2, 3]::INTEGER`
...@@ -304,13 +310,13 @@ export interface WhereOperators { ...@@ -304,13 +310,13 @@ export interface WhereOperators {
} }
/** Example: `[Op.or]: [{a: 5}, {a: 6}]` becomes `(a = 5 OR a = 6)` */ /** Example: `[Op.or]: [{a: 5}, {a: 6}]` becomes `(a = 5 OR a = 6)` */
export interface OrOperator { export interface OrOperator<TAttributes = any> {
[Op.or]: WhereOptions | WhereOptions[] | WhereValue | WhereValue[]; [Op.or]: WhereOptions<TAttributes> | WhereOptions<TAttributes>[] | WhereValue<TAttributes> | WhereValue<TAttributes>[];
} }
/** Example: `[Op.and]: {a: 5}` becomes `AND (a = 5)` */ /** Example: `[Op.and]: {a: 5}` becomes `AND (a = 5)` */
export interface AndOperator { export interface AndOperator<TAttributes = any> {
[Op.and]: WhereOptions | WhereOptions[] | WhereValue | WhereValue[]; [Op.and]: WhereOptions<TAttributes> | WhereOptions<TAttributes>[] | WhereValue<TAttributes> | WhereValue<TAttributes>[];
} }
/** /**
...@@ -325,7 +331,7 @@ export interface WhereGeometryOptions { ...@@ -325,7 +331,7 @@ export interface WhereGeometryOptions {
* Used for the right hand side of WhereAttributeHash. * Used for the right hand side of WhereAttributeHash.
* WhereAttributeHash is in there for JSON columns. * WhereAttributeHash is in there for JSON columns.
*/ */
export type WhereValue = export type WhereValue<TAttributes = any> =
| string // literal value | string // literal value
| number // literal value | number // literal value
| boolean // literal value | boolean // literal value
...@@ -333,20 +339,18 @@ export type WhereValue = ...@@ -333,20 +339,18 @@ export type WhereValue =
| Buffer // literal value | Buffer // literal value
| null | null
| WhereOperators | WhereOperators
| WhereAttributeHash // for JSON columns | WhereAttributeHash<any> // for JSON columns
| Col // reference another column | Col // reference another column
| Fn | Fn
| OrOperator | OrOperator<TAttributes>
| AndOperator | AndOperator<TAttributes>
| WhereGeometryOptions | WhereGeometryOptions
| (string | number | Buffer | WhereAttributeHash)[] // implicit [Op.or] | (string | number | Buffer | WhereAttributeHash<TAttributes>)[]; // implicit [Op.or]
// allow optional values in where object types
// Sequelize will still throw when a value in the object has the value undefined
| undefined;
/** /**
* A hash of attributes to describe your search. * A hash of attributes to describe your search.
*/ */
export interface WhereAttributeHash { export type WhereAttributeHash<TAttributes = any> = {
/** /**
* Possible key values: * Possible key values:
* - A simple attribute name * - A simple attribute name
...@@ -358,12 +362,12 @@ export interface WhereAttributeHash { ...@@ -358,12 +362,12 @@ export interface WhereAttributeHash {
* } * }
* } * }
*/ */
[field: string]: WhereValue | WhereOptions; [field in keyof TAttributes]?: WhereValue<TAttributes> | WhereOptions<TAttributes>;
} }
/** /**
* Through options for Include Options * Through options for Include Options
*/ */
export interface IncludeThroughOptions extends Filterable, Projectable { export interface IncludeThroughOptions extends Filterable<any>, Projectable {
/** /**
* The alias of the relation, in case the model you want to eagerly load is aliassed. For `hasOne` / * The alias of the relation, in case the model you want to eagerly load is aliassed. For `hasOne` /
* `belongsTo`, this should be the singular name, and for `hasMany`, it should be the plural * `belongsTo`, this should be the singular name, and for `hasMany`, it should be the plural
...@@ -379,7 +383,7 @@ export type Includeable = typeof Model | Association | IncludeOptions | { all: t ...@@ -379,7 +383,7 @@ export type Includeable = typeof Model | Association | IncludeOptions | { all: t
/** /**
* Complex include options * Complex include options
*/ */
export interface IncludeOptions extends Filterable, Projectable, Paranoid { export interface IncludeOptions extends Filterable<any>, Projectable, Paranoid {
/** /**
* Mark the include as duplicating, will prevent a subquery from being used. * Mark the include as duplicating, will prevent a subquery from being used.
*/ */
...@@ -403,13 +407,13 @@ export interface IncludeOptions extends Filterable, Projectable, Paranoid { ...@@ -403,13 +407,13 @@ export interface IncludeOptions extends Filterable, Projectable, Paranoid {
/** /**
* Custom `on` clause, overrides default. * Custom `on` clause, overrides default.
*/ */
on?: WhereOptions; on?: WhereOptions<any>;
/** /**
* Note that this converts the eager load to an inner join, * Note that this converts the eager load to an inner join,
* unless you explicitly set `required: false` * unless you explicitly set `required: false`
*/ */
where?: WhereOptions; where?: WhereOptions<any>;
/** /**
* If true, converts to an inner join, which means that the parent model will only be loaded if it has any * If true, converts to an inner join, which means that the parent model will only be loaded if it has any
...@@ -453,7 +457,7 @@ export interface IncludeOptions extends Filterable, Projectable, Paranoid { ...@@ -453,7 +457,7 @@ export interface IncludeOptions extends Filterable, Projectable, Paranoid {
subQuery?: boolean; subQuery?: boolean;
} }
type OrderItemAssociation = Association | typeof Model | { model: typeof Model; as: string } | string type OrderItemAssociation = Association | ModelStatic<Model> | { model: ModelStatic<Model>; as: string } | string
type OrderItemColumn = string | Col | Fn | Literal type OrderItemColumn = string | Col | Fn | Literal
export type OrderItem = export type OrderItem =
| string | string
...@@ -507,7 +511,9 @@ type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> ...@@ -507,7 +511,9 @@ type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
* *
* A hash of options to describe the scope of the search * A hash of options to describe the scope of the search
*/ */
export interface FindOptions extends QueryOptions, Filterable, Projectable, Paranoid, IndexHintable { export interface FindOptions<TAttributes = any>
extends QueryOptions, Filterable<TAttributes>, Projectable, Paranoid, IndexHintable
{
/** /**
* A list of associations to eagerly load using a left join (a single association is also supported). Supported is either * A list of associations to eagerly load using a left join (a single association is also supported). Supported is either
* `{ include: Model1 }`, `{ include: [ Model1, Model2, ...]}`, `{ include: [{ model: Model1, as: 'Alias' }]}` or * `{ include: Model1 }`, `{ include: [ Model1, Model2, ...]}`, `{ include: [{ model: Model1, as: 'Alias' }]}` or
...@@ -547,7 +553,7 @@ export interface FindOptions extends QueryOptions, Filterable, Projectable, Para ...@@ -547,7 +553,7 @@ export interface FindOptions extends QueryOptions, Filterable, Projectable, Para
*/ */
lock?: lock?:
| LOCK | LOCK
| { level: LOCK; of: typeof Model } | { level: LOCK; of: ModelStatic<Model> }
| boolean; | boolean;
/** /**
* Skip locked rows. Only supported in Postgres. * Skip locked rows. Only supported in Postgres.
...@@ -562,7 +568,7 @@ export interface FindOptions extends QueryOptions, Filterable, Projectable, Para ...@@ -562,7 +568,7 @@ export interface FindOptions extends QueryOptions, Filterable, Projectable, Para
/** /**
* Select group rows after groups and aggregates are computed. * Select group rows after groups and aggregates are computed.
*/ */
having?: WhereOptions; having?: WhereOptions<any>;
/** /**
* Use sub queries (internal) * Use sub queries (internal)
...@@ -570,7 +576,7 @@ export interface FindOptions extends QueryOptions, Filterable, Projectable, Para ...@@ -570,7 +576,7 @@ export interface FindOptions extends QueryOptions, Filterable, Projectable, Para
subQuery?: boolean; subQuery?: boolean;
} }
export interface NonNullFindOptions extends FindOptions { export interface NonNullFindOptions<TAttributes = any> extends FindOptions<TAttributes> {
/** /**
* Throw if nothing was found. * Throw if nothing was found.
*/ */
...@@ -580,7 +586,9 @@ export interface NonNullFindOptions extends FindOptions { ...@@ -580,7 +586,9 @@ export interface NonNullFindOptions extends FindOptions {
/** /**
* Options for Model.count method * Options for Model.count method
*/ */
export interface CountOptions extends Logging, Transactionable, Filterable, Projectable, Paranoid, Poolable { export interface CountOptions<TAttributes = any>
extends Logging, Transactionable, Filterable<TAttributes>, Projectable, Paranoid, Poolable
{
/** /**
* Include options. See `find` for details * Include options. See `find` for details
*/ */
...@@ -607,7 +615,7 @@ export interface CountOptions extends Logging, Transactionable, Filterable, Proj ...@@ -607,7 +615,7 @@ export interface CountOptions extends Logging, Transactionable, Filterable, Proj
/** /**
* Options for Model.count when GROUP BY is used * Options for Model.count when GROUP BY is used
*/ */
export interface CountWithOptions extends CountOptions { export interface CountWithOptions<TAttributes = any> extends CountOptions<TAttributes> {
/** /**
* GROUP BY in sql * GROUP BY in sql
* Used in conjunction with `attributes`. * Used in conjunction with `attributes`.
...@@ -616,7 +624,7 @@ export interface CountWithOptions extends CountOptions { ...@@ -616,7 +624,7 @@ export interface CountWithOptions extends CountOptions {
group: GroupOption; group: GroupOption;
} }
export interface FindAndCountOptions extends CountOptions, FindOptions { } export interface FindAndCountOptions<TAttributes = any> extends CountOptions<TAttributes>, FindOptions<TAttributes> { }
/** /**
* Options for Model.build method * Options for Model.build method
...@@ -652,11 +660,11 @@ export interface Silent { ...@@ -652,11 +660,11 @@ export interface Silent {
/** /**
* Options for Model.create method * Options for Model.create method
*/ */
export interface CreateOptions extends BuildOptions, Logging, Silent, Transactionable, Hookable { export interface CreateOptions<TAttributes = any> extends BuildOptions, Logging, Silent, Transactionable, Hookable {
/** /**
* If set, only columns matching those in fields will be saved * If set, only columns matching those in fields will be saved
*/ */
fields?: string[]; fields?: (keyof TAttributes)[];
/** /**
* On Duplicate * On Duplicate
...@@ -685,28 +693,30 @@ export interface Hookable { ...@@ -685,28 +693,30 @@ export interface Hookable {
/** /**
* Options for Model.findOrCreate method * Options for Model.findOrCreate method
*/ */
export interface FindOrCreateOptions extends Filterable, Logging, Transactionable { export interface FindOrCreateOptions<TAttributes = any, TCreationAttributes = TAttributes>
extends FindOptions<TAttributes>
{
/** /**
* The fields to insert / update. Defaults to all fields * The fields to insert / update. Defaults to all fields
*/ */
fields?: string[]; fields?: (keyof TAttributes)[];
/** /**
* Default values to use if building a new instance * Default values to use if building a new instance
*/ */
defaults?: object; defaults?: TCreationAttributes;
} }
/** /**
* Options for Model.upsert method * Options for Model.upsert method
*/ */
export interface UpsertOptions extends Logging, Transactionable, SearchPathable, Hookable { export interface UpsertOptions<TAttributes = any> extends Logging, Transactionable, SearchPathable, Hookable {
/** /**
* The fields to insert / update. Defaults to all fields * The fields to insert / update. Defaults to all fields
*/ */
fields?: string[]; fields?: (keyof TAttributes)[];
/** /**
* Return the affected rows * Return the affected rows (only for postgres)
*/ */
returning?: boolean; returning?: boolean;
...@@ -719,11 +729,11 @@ export interface UpsertOptions extends Logging, Transactionable, SearchPathable, ...@@ -719,11 +729,11 @@ export interface UpsertOptions extends Logging, Transactionable, SearchPathable,
/** /**
* Options for Model.bulkCreate method * Options for Model.bulkCreate method
*/ */
export interface BulkCreateOptions extends Logging, Transactionable, Hookable { export interface BulkCreateOptions<TAttributes = any> extends Logging, Transactionable, Hookable {
/** /**
* Fields to insert (defaults to all fields) * Fields to insert (defaults to all fields)
*/ */
fields?: string[]; fields?: (keyof TAttributes)[];
/** /**
* Should each row be subject to validation before it is inserted. The whole insert will fail if one row * Should each row be subject to validation before it is inserted. The whole insert will fail if one row
...@@ -748,7 +758,7 @@ export interface BulkCreateOptions extends Logging, Transactionable, Hookable { ...@@ -748,7 +758,7 @@ export interface BulkCreateOptions extends Logging, Transactionable, Hookable {
* Fields to update if row key already exists (on duplicate key update)? (only supported by MySQL, * Fields to update if row key already exists (on duplicate key update)? (only supported by MySQL,
* MariaDB, SQLite >= 3.24.0 & Postgres >= 9.5). By default, all fields are updated. * MariaDB, SQLite >= 3.24.0 & Postgres >= 9.5). By default, all fields are updated.
*/ */
updateOnDuplicate?: string[]; updateOnDuplicate?: (keyof TAttributes)[];
/** /**
* Include options. See `find` for details * Include options. See `find` for details
...@@ -758,13 +768,13 @@ export interface BulkCreateOptions extends Logging, Transactionable, Hookable { ...@@ -758,13 +768,13 @@ export interface BulkCreateOptions extends Logging, Transactionable, Hookable {
/** /**
* Return all columns or only the specified columns for the affected rows (only for postgres) * Return all columns or only the specified columns for the affected rows (only for postgres)
*/ */
returning?: boolean | string[]; returning?: boolean | (keyof TAttributes)[];
} }
/** /**
* The options passed to Model.destroy in addition to truncate * The options passed to Model.destroy in addition to truncate
*/ */
export interface TruncateOptions extends Logging, Transactionable, Filterable, Hookable { export interface TruncateOptions<TAttributes = any> extends Logging, Transactionable, Filterable<TAttributes>, Hookable {
/** /**
* Only used in conjuction with TRUNCATE. Truncates all tables that have foreign-key references to the * Only used in conjuction with TRUNCATE. Truncates all tables that have foreign-key references to the
* named table, or to any tables added to the group due to CASCADE. * named table, or to any tables added to the group due to CASCADE.
...@@ -799,7 +809,7 @@ export interface TruncateOptions extends Logging, Transactionable, Filterable, H ...@@ -799,7 +809,7 @@ export interface TruncateOptions extends Logging, Transactionable, Filterable, H
/** /**
* Options used for Model.destroy * Options used for Model.destroy
*/ */
export interface DestroyOptions extends TruncateOptions { export interface DestroyOptions<TAttributes = any> extends TruncateOptions<TAttributes> {
/** /**
* If set to true, dialects that support it will use TRUNCATE instead of DELETE FROM. If a table is * If set to true, dialects that support it will use TRUNCATE instead of DELETE FROM. If a table is
* truncated the where and limit options are ignored * truncated the where and limit options are ignored
...@@ -810,7 +820,7 @@ export interface DestroyOptions extends TruncateOptions { ...@@ -810,7 +820,7 @@ export interface DestroyOptions extends TruncateOptions {
/** /**
* Options for Model.restore * Options for Model.restore
*/ */
export interface RestoreOptions extends Logging, Transactionable, Filterable, Hookable { export interface RestoreOptions<TAttributes = any> extends Logging, Transactionable, Filterable<TAttributes>, Hookable {
/** /**
* If set to true, restore will find all records within the where parameter and will execute before / after * If set to true, restore will find all records within the where parameter and will execute before / after
...@@ -827,16 +837,16 @@ export interface RestoreOptions extends Logging, Transactionable, Filterable, Ho ...@@ -827,16 +837,16 @@ export interface RestoreOptions extends Logging, Transactionable, Filterable, Ho
/** /**
* Options used for Model.update * Options used for Model.update
*/ */
export interface UpdateOptions extends Logging, Transactionable, Paranoid, Hookable { export interface UpdateOptions<TAttributes = any> extends Logging, Transactionable, Paranoid, Hookable {
/** /**
* Options to describe the scope of the search. * Options to describe the scope of the search.
*/ */
where: WhereOptions; where: WhereOptions<TAttributes>;
/** /**
* Fields to update (defaults to all fields) * Fields to update (defaults to all fields)
*/ */
fields?: string[]; fields?: (keyof TAttributes)[];
/** /**
* Should each row be subject to validation before it is inserted. The whole insert will fail if one row * Should each row be subject to validation before it is inserted. The whole insert will fail if one row
...@@ -880,7 +890,9 @@ export interface UpdateOptions extends Logging, Transactionable, Paranoid, Hooka ...@@ -880,7 +890,9 @@ export interface UpdateOptions extends Logging, Transactionable, Paranoid, Hooka
/** /**
* Options used for Model.aggregate * Options used for Model.aggregate
*/ */
export interface AggregateOptions<T extends DataType | unknown> extends QueryOptions, Filterable, Paranoid { export interface AggregateOptions<T extends DataType | unknown, TAttributes = any>
extends QueryOptions, Filterable<TAttributes>, Paranoid
{
/** /**
* The type of the result. If `field` is a field in this Model, the default will be the type of that field, * The type of the result. If `field` is a field in this Model, the default will be the type of that field,
* otherwise defaults to float. * otherwise defaults to float.
...@@ -898,12 +910,13 @@ export interface AggregateOptions<T extends DataType | unknown> extends QueryOpt ...@@ -898,12 +910,13 @@ export interface AggregateOptions<T extends DataType | unknown> extends QueryOpt
/** /**
* Options used for Instance.increment method * Options used for Instance.increment method
*/ */
export interface IncrementDecrementOptions extends Logging, Transactionable, Silent, SearchPathable, Filterable { } export interface IncrementDecrementOptions<TAttributes = any>
extends Logging, Transactionable, Silent, SearchPathable, Filterable<TAttributes> { }
/** /**
* Options used for Instance.increment method * Options used for Instance.increment method
*/ */
export interface IncrementDecrementOptionsWithBy extends IncrementDecrementOptions { export interface IncrementDecrementOptionsWithBy<TAttributes = any> extends IncrementDecrementOptions<TAttributes> {
/** /**
* The number to increment by * The number to increment by
* *
...@@ -930,7 +943,8 @@ export interface InstanceDestroyOptions extends Logging, Transactionable { ...@@ -930,7 +943,8 @@ export interface InstanceDestroyOptions extends Logging, Transactionable {
/** /**
* Options used for Instance.update method * Options used for Instance.update method
*/ */
export interface InstanceUpdateOptions extends SaveOptions, SetOptions, Filterable { } export interface InstanceUpdateOptions<TAttributes = any> extends
SaveOptions<TAttributes>, SetOptions, Filterable<TAttributes> { }
/** /**
* Options used for Instance.set method * Options used for Instance.set method
...@@ -950,12 +964,12 @@ export interface SetOptions { ...@@ -950,12 +964,12 @@ export interface SetOptions {
/** /**
* Options used for Instance.save method * Options used for Instance.save method
*/ */
export interface SaveOptions extends Logging, Transactionable, Silent { export interface SaveOptions<TAttributes = any> extends Logging, Transactionable, Silent {
/** /**
* An optional array of strings, representing database columns. If fields is provided, only those columns * An optional array of strings, representing database columns. If fields is provided, only those columns
* will be validated and saved. * will be validated and saved.
*/ */
fields?: string[]; fields?: (keyof TAttributes)[];
/** /**
* If false, validations won't be run. * If false, validations won't be run.
...@@ -1191,11 +1205,11 @@ export interface ModelSetterOptions<M extends Model = Model> { ...@@ -1191,11 +1205,11 @@ export interface ModelSetterOptions<M extends Model = Model> {
/** /**
* Interface for Define Scope Options * Interface for Define Scope Options
*/ */
export interface ModelScopeOptions { export interface ModelScopeOptions<TAttributes = any> {
/** /**
* Name of the scope and it's query * Name of the scope and it's query
*/ */
[scopeName: string]: FindOptions | ((...args: any[]) => FindOptions); [scopeName: string]: FindOptions<TAttributes> | ((...args: any[]) => FindOptions<TAttributes>);
} }
/** /**
...@@ -1338,11 +1352,11 @@ export interface ModelAttributeColumnOptions<M extends Model = Model> extends Co ...@@ -1338,11 +1352,11 @@ export interface ModelAttributeColumnOptions<M extends Model = Model> extends Co
/** /**
* Interface for Attributes provided for a column * Interface for Attributes provided for a column
*/ */
export interface ModelAttributes<M extends Model = Model> { export type ModelAttributes<M extends Model = Model, TCreationAttributes = any> = {
/** /**
* The description of a database column * The description of a database column
*/ */
[name: string]: DataType | ModelAttributeColumnOptions<M>; [name in keyof TCreationAttributes]: DataType | ModelAttributeColumnOptions<M>;
} }
/** /**
...@@ -1358,13 +1372,13 @@ export interface ModelOptions<M extends Model = Model> { ...@@ -1358,13 +1372,13 @@ export interface ModelOptions<M extends Model = Model> {
* Define the default search scope to use for this model. Scopes have the same form as the options passed to * Define the default search scope to use for this model. Scopes have the same form as the options passed to
* find / findAll. * find / findAll.
*/ */
defaultScope?: FindOptions; defaultScope?: FindOptions<M['_attributes']>;
/** /**
* More scopes, defined in the same way as defaultScope above. See `Model.scope` for more information about * More scopes, defined in the same way as defaultScope above. See `Model.scope` for more information about
* how scopes are defined, and what you can do with them * how scopes are defined, and what you can do with them
*/ */
scopes?: ModelScopeOptions; scopes?: ModelScopeOptions<M['_attributes']>;
/** /**
* Don't persits null values. This means that all columns with null values will not be saved. * Don't persits null values. This means that all columns with null values will not be saved.
...@@ -1464,7 +1478,7 @@ export interface ModelOptions<M extends Model = Model> { ...@@ -1464,7 +1478,7 @@ export interface ModelOptions<M extends Model = Model> {
* See Hooks for more information about hook * See Hooks for more information about hook
* functions and their signatures. Each property can either be a function, or an array of functions. * functions and their signatures. Each property can either be a function, or an array of functions.
*/ */
hooks?: Partial<ModelHooks<M>>; hooks?: Partial<ModelHooks<M, M['_attributes']>>;
/** /**
* An object of model wide validations. Validations have access to all model values via `this`. If the * An object of model wide validations. Validations have access to all model values via `this`. If the
...@@ -1514,7 +1528,31 @@ export interface AddScopeOptions { ...@@ -1514,7 +1528,31 @@ export interface AddScopeOptions {
override: boolean; override: boolean;
} }
export abstract class Model<T = any, T2 = any> extends Hooks { export abstract class Model<TModelAttributes extends {} = any, TCreationAttributes extends {} = TModelAttributes>
extends Hooks<Model<TModelAttributes, TCreationAttributes>, TModelAttributes, TCreationAttributes>
{
/**
* A dummy variable that doesn't exist on the real object. This exists so
* Typescript can infer the type of the attributes in static functions. Don't
* try to access this!
*
* Before using these, I'd tried typing out the functions without them, but
* Typescript fails to infer `TAttributes` in signatures like the below.
*
* ```ts
* public static findOne<M extends Model<TAttributes>, TAttributes>(
* this: { new(): M },
* options: NonNullFindOptions<TAttributes>
* ): Promise<M>;
* ```
*/
_attributes: TModelAttributes;
/**
* A similar dummy variable that doesn't exist on the real object. Do not
* try to access this in real code.
*/
_creationAttributes: TCreationAttributes;
/** The name of the database table */ /** The name of the database table */
public static readonly tableName: string; public static readonly tableName: string;
...@@ -1593,7 +1631,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1593,7 +1631,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param options These options are merged with the default define options provided to the Sequelize constructor * @param options These options are merged with the default define options provided to the Sequelize constructor
* @return Return the initialized model * @return Return the initialized model
*/ */
public static init<M extends Model = Model>(this: ModelCtor<M>, attributes: ModelAttributes<M>, options: InitOptions<M>): Model; public static init<M extends Model>(
this: ModelStatic<M>,
attributes: ModelAttributes<M, M['_creationAttributes']>, options: InitOptions<M>
): Model;
/** /**
* Remove attribute from model definition * Remove attribute from model definition
...@@ -1606,7 +1647,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1606,7 +1647,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* Sync this Model to the DB, that is create the table. Upon success, the callback will be called with the * Sync this Model to the DB, that is create the table. Upon success, the callback will be called with the
* model instance (this) * model instance (this)
*/ */
public static sync(options?: SyncOptions): Promise<Model>; public static sync<M extends Model>(options?: SyncOptions): Promise<M>;
/** /**
* Drop the table represented by this Model * Drop the table represented by this Model
...@@ -1625,7 +1666,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1625,7 +1666,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param options * @param options
*/ */
public static schema<M extends Model>( public static schema<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
schema: string, schema: string,
options?: SchemaOptions options?: SchemaOptions
): { new(): M } & typeof Model; ): { new(): M } & typeof Model;
...@@ -1694,10 +1735,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1694,10 +1735,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @return Model A reference to the model, with the scope(s) applied. Calling scope again on the returned * @return Model A reference to the model, with the scope(s) applied. Calling scope again on the returned
* model will clear the previous scope. * model will clear the previous scope.
*/ */
public static scope<M extends { new(): Model }>( public static scope<M extends Model>(
this: M, this: ModelStatic<M>,
options?: string | ScopeOptions | (string | ScopeOptions)[] | WhereAttributeHash options?: string | ScopeOptions | (string | ScopeOptions)[] | WhereAttributeHash<M>
): M; ): ModelCtor<M>;
/** /**
* Add a new scope to the model * Add a new scope to the model
...@@ -1707,8 +1748,18 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1707,8 +1748,18 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* error if a scope with that name already exists. Pass `override: true` in the options * error if a scope with that name already exists. Pass `override: true` in the options
* object to silence this error. * object to silence this error.
*/ */
public static addScope(name: string, scope: FindOptions, options?: AddScopeOptions): void; public static addScope<M extends Model>(
public static addScope(name: string, scope: (...args: any[]) => FindOptions, options?: AddScopeOptions): void; this: ModelStatic<M>,
name: string,
scope: FindOptions<M['_attributes']>,
options?: AddScopeOptions
): void;
public static addScope<M extends Model>(
this: ModelStatic<M>,
name: string,
scope: (...args: any[]) => FindOptions<M['_attributes']>,
options?: AddScopeOptions
): void;
/** /**
* Search for multiple instances. * Search for multiple instances.
...@@ -1772,30 +1823,35 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1772,30 +1823,35 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* *
* @see {Sequelize#query} * @see {Sequelize#query}
*/ */
public static findAll<M extends Model>(this: { new(): M } & typeof Model, options?: FindOptions): Promise<M[]>; public static findAll<M extends Model>(
this: ModelStatic<M>,
options?: FindOptions<M['_attributes']>): Promise<M[]>;
/** /**
* Search for a single instance by its primary key. This applies LIMIT 1, so the listener will * Search for a single instance by its primary key. This applies LIMIT 1, so the listener will
* always be called with a single instance. * always be called with a single instance.
*/ */
public static findByPk<M extends Model>( public static findByPk<M extends Model>(
this: { new (): M } & typeof Model, this: ModelStatic<M>,
identifier: Identifier, identifier: Identifier,
options: Omit<NonNullFindOptions, 'where'> options: Omit<NonNullFindOptions<M['_attributes']>, 'where'>
): Promise<M>; ): Promise<M>;
public static findByPk<M extends Model>( public static findByPk<M extends Model>(
this: { new (): M } & typeof Model, this: ModelStatic<M>,
identifier?: Identifier, identifier?: Identifier,
options?: Omit<FindOptions, 'where'> options?: Omit<FindOptions<M['_attributes']>, 'where'>
): Promise<M | null>; ): Promise<M | null>;
/** /**
* Search for a single instance. Returns the first instance found, or null if none can be found. * Search for a single instance. Returns the first instance found, or null if none can be found.
*/ */
public static findOne<M extends Model>(this: { new (): M } & typeof Model, options: NonNullFindOptions): Promise<M>;
public static findOne<M extends Model>( public static findOne<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
options?: FindOptions options: NonNullFindOptions<M['_attributes']>
): Promise<M>;
public static findOne<M extends Model>(
this: ModelStatic<M>,
options?: FindOptions<M['_attributes']>
): Promise<M | null>; ): Promise<M | null>;
/** /**
...@@ -1807,38 +1863,47 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1807,38 +1863,47 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @return Returns the aggregate result cast to `options.dataType`, unless `options.plain` is false, in * @return Returns the aggregate result cast to `options.dataType`, unless `options.plain` is false, in
* which case the complete data result is returned. * which case the complete data result is returned.
*/ */
public static aggregate<M extends Model, T extends DataType | unknown>( public static aggregate<T, M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
field: keyof M, field: keyof M['_attributes'] | '*',
aggregateFunction: string, aggregateFunction: string,
options?: AggregateOptions<T> options?: AggregateOptions<T, M['_attributes']>
): Promise<T>; ): Promise<T>;
/** /**
* Count number of records if group by is used * Count number of records if group by is used
*/ */
public static count(options: CountWithOptions): Promise<{ [key: string]: number }>; public static count<M extends Model>(
this: ModelStatic<M>,
options: CountWithOptions<M['_attributes']>
): Promise<{ [key: string]: number }>;
/** /**
* Count the number of records matching the provided where clause. * Count the number of records matching the provided where clause.
* *
* If you provide an `include` option, the number of matching associations will be counted instead. * If you provide an `include` option, the number of matching associations will be counted instead.
*/ */
public static count(options?: CountOptions): Promise<number>; public static count<M extends Model>(
this: ModelStatic<M>,
options?: CountOptions<M['_attributes']>
): Promise<number>;
/** /**
* Find all the rows matching your query, within a specified offset / limit, and get the total number of * Find all the rows matching your query, within a specified offset / limit, and get the total number of
* rows matching your query. This is very usefull for paging * rows matching your query. This is very usefull for paging
* *
* ```js * ```js
* const { rows, count } = await Model.findAndCountAll({ * Model.findAndCountAll({
* where: ..., * where: ...,
* limit: 12, * limit: 12,
* offset: 12 * offset: 12
* }); * }).then(result => {
* ...
* })
* ``` * ```
* In the above example, `rows` will contain rows 13 through 24, while `count` will return * In the above example, `result.rows` will contain rows 13 through 24, while `result.count` will return
* the total number of rows that matched your query. * the
* total number of rows that matched your query.
* *
* When you add includes, only those which are required (either because they have a where clause, or * When you add includes, only those which are required (either because they have a where clause, or
* because * because
...@@ -1859,43 +1924,43 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1859,43 +1924,43 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* profiles will be counted * profiles will be counted
*/ */
public static findAndCountAll<M extends Model>( public static findAndCountAll<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
options?: FindAndCountOptions options?: FindAndCountOptions<M['_attributes']>
): Promise<{ rows: M[]; count: number }>; ): Promise<{ rows: M[]; count: number }>;
/** /**
* Find the maximum value of field * Find the maximum value of field
*/ */
public static max<M extends Model, T extends DataType | unknown>( public static max<T extends DataType | unknown, M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
field: keyof M, field: keyof M['_attributes'],
options?: AggregateOptions<T> options?: AggregateOptions<T, M['_attributes']>
): Promise<T>; ): Promise<T>;
/** /**
* Find the minimum value of field * Find the minimum value of field
*/ */
public static min<M extends Model, T extends DataType | unknown>( public static min<T extends DataType | unknown, M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
field: keyof M, field: keyof M['_attributes'],
options?: AggregateOptions<T> options?: AggregateOptions<T, M['_attributes']>
): Promise<T>; ): Promise<T>;
/** /**
* Find the sum of field * Find the sum of field
*/ */
public static sum<M extends Model, T extends DataType | unknown>( public static sum<T extends DataType | unknown, M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
field: keyof M, field: keyof M['_attributes'],
options?: AggregateOptions<T> options?: AggregateOptions<T, M['_attributes']>
): Promise<number>; ): Promise<number>;
/** /**
* Builds a new model instance. Values is an object of key value pairs, must be defined but can be empty. * Builds a new model instance. Values is an object of key value pairs, must be defined but can be empty.
*/ */
public static build<M extends Model>( public static build<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
record?: object, record?: M['_creationAttributes'],
options?: BuildOptions options?: BuildOptions
): M; ): M;
...@@ -1903,8 +1968,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1903,8 +1968,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* Undocumented bulkBuild * Undocumented bulkBuild
*/ */
public static bulkBuild<M extends Model>( public static bulkBuild<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
records: object[], records: (M['_creationAttributes'])[],
options?: BuildOptions options?: BuildOptions
): M[]; ): M[];
...@@ -1912,24 +1977,28 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1912,24 +1977,28 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* Builds a new model instance and calls save on it. * Builds a new model instance and calls save on it.
*/ */
public static create<M extends Model>( public static create<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
values?: object, values?: M['_creationAttributes'],
options?: CreateOptions options?: CreateOptions<M['_attributes']>
): Promise<M>; ): Promise<M>;
public static create(values: object, options: CreateOptions & { returning: false }): Promise<void>; public static create<M extends Model>(
this: ModelStatic<M>,
values: M['_creationAttributes'],
options: CreateOptions<M['_attributes']> & { returning: false }
): Promise<void>;
/** /**
* Find a row that matches the query, or build (but don't save) the row if none is found. * Find a row that matches the query, or build (but don't save) the row if none is found.
* The successful result of the promise will be [instance, initialized] - Make sure to use destructuring such as `const [instance, wasBuilt] = ...` * The successfull result of the promise will be (instance, initialized) - Make sure to use `.then(([...]))`
*/ */
public static findOrBuild<M extends Model>( public static findOrBuild<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
options: FindOrCreateOptions options: FindOrCreateOptions<M['_attributes'], M['_creationAttributes']>
): Promise<[M, boolean]>; ): Promise<[M, boolean]>;
/** /**
* Find a row that matches the query, or build and save the row if none is found * Find a row that matches the query, or build and save the row if none is found
* The successful result of the promise will be [instance, created] - Make sure to use destructuring such as `const [instance, wasCreated] = ...` * The successful result of the promise will be (instance, created) - Make sure to use `.then(([...]))`
* *
* If no transaction is passed in the `options` object, a new transaction will be created internally, to * If no transaction is passed in the `options` object, a new transaction will be created internally, to
* prevent the race condition where a matching row is created by another connection after the find but * prevent the race condition where a matching row is created by another connection after the find but
...@@ -1939,8 +2008,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1939,8 +2008,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* will be created instead, and any unique constraint violation will be handled internally. * will be created instead, and any unique constraint violation will be handled internally.
*/ */
public static findOrCreate<M extends Model>( public static findOrCreate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
options: FindOrCreateOptions options: FindOrCreateOptions<M['_attributes'], M['_creationAttributes']>
): Promise<[M, boolean]>; ): Promise<[M, boolean]>;
/** /**
...@@ -1948,8 +2017,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1948,8 +2017,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* Will execute a find call, if empty then attempt to create, if unique constraint then attempt to find again * Will execute a find call, if empty then attempt to create, if unique constraint then attempt to find again
*/ */
public static findCreateFind<M extends Model>( public static findCreateFind<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
options: FindOrCreateOptions options: FindOrCreateOptions<M['_attributes'], M['_creationAttributes']>
): Promise<[M, boolean]>; ): Promise<[M, boolean]>;
/** /**
...@@ -1960,17 +2029,21 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1960,17 +2029,21 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* *
* **Implementation details:** * **Implementation details:**
* *
* * MySQL - Implemented with ON DUPLICATE KEY UPDATE * * MySQL - Implemented as a single query `INSERT values ON DUPLICATE KEY UPDATE values`
* * PostgreSQL - Implemented with ON CONFLICT DO UPDATE * * PostgreSQL - Implemented as a temporary function with exception handling: INSERT EXCEPTION WHEN
* * SQLite - Implemented with ON CONFLICT DO UPDATE * unique_constraint UPDATE
* * MSSQL - Implemented with MERGE statement * * SQLite - Implemented as two queries `INSERT; UPDATE`. This means that the update is executed
* regardless
* of whether the row already existed or not
* *
* **Note** that PostgreSQL/SQLite returns null for created, no matter if the row was created or updated. * **Note** that SQLite returns null for created, no matter if the row was created or updated. This is
* because SQLite always runs INSERT OR IGNORE + UPDATE, in a single query, so there is no way to know
* whether the row was inserted or not.
*/ */
public static upsert<M extends Model>( public static upsert<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
values: object, values: M['_creationAttributes'],
options?: UpsertOptions options?: UpsertOptions<M['_attributes']>
): Promise<[M, boolean | null]>; ): Promise<[M, boolean | null]>;
/** /**
...@@ -1985,27 +2058,36 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1985,27 +2058,36 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param records List of objects (key/value pairs) to create instances from * @param records List of objects (key/value pairs) to create instances from
*/ */
public static bulkCreate<M extends Model>( public static bulkCreate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
records: object[], records: (M['_creationAttributes'])[],
options?: BulkCreateOptions options?: BulkCreateOptions<M['_attributes']>
): Promise<M[]>; ): Promise<M[]>;
/** /**
* Truncate all instances of the model. This is a convenient method for Model.destroy({ truncate: true }). * Truncate all instances of the model. This is a convenient method for Model.destroy({ truncate: true }).
*/ */
public static truncate(options?: TruncateOptions): Promise<void>; public static truncate<M extends Model>(
this: ModelStatic<M>,
options?: TruncateOptions<M['_attributes']>
): Promise<void>;
/** /**
* Delete multiple instances, or set their deletedAt timestamp to the current time if `paranoid` is enabled. * Delete multiple instances, or set their deletedAt timestamp to the current time if `paranoid` is enabled.
* *
* @return Promise<number> The number of destroyed rows * @return Promise<number> The number of destroyed rows
*/ */
public static destroy(options?: DestroyOptions): Promise<number>; public static destroy<M extends Model>(
this: ModelStatic<M>,
options?: DestroyOptions<M['_attributes']>
): Promise<number>;
/** /**
* Restore multiple instances if `paranoid` is enabled. * Restore multiple instances if `paranoid` is enabled.
*/ */
public static restore(options?: RestoreOptions): Promise<void>; public static restore<M extends Model>(
this: ModelStatic<M>,
options?: RestoreOptions<M['_attributes']>
): Promise<void>;
/** /**
* Update multiple instances that match the where options. The promise returns an array with one or two * Update multiple instances that match the where options. The promise returns an array with one or two
...@@ -2013,36 +2095,36 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2013,36 +2095,36 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* affected rows (only supported in postgres and mssql with `options.returning` true.) * affected rows (only supported in postgres and mssql with `options.returning` true.)
*/ */
public static update<M extends Model>( public static update<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
values: object, values: Partial<M['_attributes']>,
options: UpdateOptions options: UpdateOptions<M['_attributes']>
): Promise<[number, M[]]>; ): Promise<[number, M[]]>;
/** /**
* Increments a single field. * Increments a single field.
*/ */
public static increment<M extends Model, K extends keyof M>( public static increment<M extends Model>(
this: { new(): M }, this: ModelStatic<M>,
field: K, field: keyof M['_attributes'],
options: IncrementDecrementOptionsWithBy options: IncrementDecrementOptionsWithBy<M['_attributes']>
): Promise<M>; ): Promise<M>;
/** /**
* Increments multiple fields by the same value. * Increments multiple fields by the same value.
*/ */
public static increment<M extends Model, K extends keyof M>( public static increment<M extends Model>(
this: { new(): M }, this: ModelStatic<M>,
fields: K[], fields: (keyof M['_attributes'])[],
options: IncrementDecrementOptionsWithBy options: IncrementDecrementOptionsWithBy<M['_attributes']>
): Promise<M>; ): Promise<M>;
/** /**
* Increments multiple fields by different values. * Increments multiple fields by different values.
*/ */
public static increment<M extends Model, K extends keyof M>( public static increment<M extends Model>(
this: { new(): M }, this: ModelStatic<M>,
fields: { [key in K]?: number }, fields: { [key in keyof M['_attributes']]?: number },
options: IncrementDecrementOptions options: IncrementDecrementOptions<M['_attributes']>
): Promise<M>; ): Promise<M>;
/** /**
...@@ -2063,12 +2145,12 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2063,12 +2145,12 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static beforeValidate<M extends Model>( public static beforeValidate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (instance: M, options: ValidationOptions) => HookReturn fn: (instance: M, options: ValidationOptions) => HookReturn
): void; ): void;
public static beforeValidate<M extends Model>( public static beforeValidate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (instance: M, options: ValidationOptions) => HookReturn fn: (instance: M, options: ValidationOptions) => HookReturn
): void; ): void;
...@@ -2079,12 +2161,12 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2079,12 +2161,12 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static afterValidate<M extends Model>( public static afterValidate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (instance: M, options: ValidationOptions) => HookReturn fn: (instance: M, options: ValidationOptions) => HookReturn
): void; ): void;
public static afterValidate<M extends Model>( public static afterValidate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (instance: M, options: ValidationOptions) => HookReturn fn: (instance: M, options: ValidationOptions) => HookReturn
): void; ): void;
...@@ -2095,13 +2177,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2095,13 +2177,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with attributes, options * @param fn A callback function that is called with attributes, options
*/ */
public static beforeCreate<M extends Model>( public static beforeCreate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (attributes: M, options: CreateOptions) => HookReturn fn: (instance: M, options: CreateOptions<M['_attributes']>) => HookReturn
): void; ): void;
public static beforeCreate<M extends Model>( public static beforeCreate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (attributes: M, options: CreateOptions) => HookReturn fn: (instance: M, options: CreateOptions<M['_attributes']>) => HookReturn
): void; ): void;
/** /**
...@@ -2111,13 +2193,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2111,13 +2193,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with attributes, options * @param fn A callback function that is called with attributes, options
*/ */
public static afterCreate<M extends Model>( public static afterCreate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (attributes: M, options: CreateOptions) => HookReturn fn: (instance: M, options: CreateOptions<M['_attributes']>) => HookReturn
): void; ): void;
public static afterCreate<M extends Model>( public static afterCreate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (attributes: M, options: CreateOptions) => HookReturn fn: (instance: M, options: CreateOptions<M['_attributes']>) => HookReturn
): void; ): void;
/** /**
...@@ -2127,12 +2209,12 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2127,12 +2209,12 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static beforeDestroy<M extends Model>( public static beforeDestroy<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (instance: M, options: InstanceDestroyOptions) => HookReturn fn: (instance: M, options: InstanceDestroyOptions) => HookReturn
): void; ): void;
public static beforeDestroy<M extends Model>( public static beforeDestroy<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (instance: M, options: InstanceDestroyOptions) => HookReturn fn: (instance: M, options: InstanceDestroyOptions) => HookReturn
): void; ): void;
...@@ -2143,12 +2225,12 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2143,12 +2225,12 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static afterDestroy<M extends Model>( public static afterDestroy<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (instance: M, options: InstanceDestroyOptions) => HookReturn fn: (instance: M, options: InstanceDestroyOptions) => HookReturn
): void; ): void;
public static afterDestroy<M extends Model>( public static afterDestroy<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (instance: M, options: InstanceDestroyOptions) => HookReturn fn: (instance: M, options: InstanceDestroyOptions) => HookReturn
): void; ): void;
...@@ -2159,13 +2241,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2159,13 +2241,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static beforeUpdate<M extends Model>( public static beforeUpdate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (instance: M, options: UpdateOptions) => HookReturn fn: (instance: M, options: UpdateOptions<M['_attributes']>) => HookReturn
): void; ): void;
public static beforeUpdate<M extends Model>( public static beforeUpdate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (instance: M, options: UpdateOptions) => HookReturn fn: (instance: M, options: UpdateOptions<M['_attributes']>) => HookReturn
): void; ): void;
/** /**
...@@ -2175,13 +2257,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2175,13 +2257,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static afterUpdate<M extends Model>( public static afterUpdate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (instance: M, options: UpdateOptions) => HookReturn fn: (instance: M, options: UpdateOptions<M['_attributes']>) => HookReturn
): void; ): void;
public static afterUpdate<M extends Model>( public static afterUpdate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (instance: M, options: UpdateOptions) => HookReturn fn: (instance: M, options: UpdateOptions<M['_attributes']>) => HookReturn
): void; ): void;
/** /**
...@@ -2191,13 +2273,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2191,13 +2273,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static beforeSave<M extends Model>( public static beforeSave<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (instance: M, options: UpdateOptions | SaveOptions) => HookReturn fn: (instance: M, options: UpdateOptions<M['_attributes']> | SaveOptions<M['_attributes']>) => HookReturn
): void; ): void;
public static beforeSave<M extends Model>( public static beforeSave<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (instance: M, options: UpdateOptions | SaveOptions) => HookReturn fn: (instance: M, options: UpdateOptions<M['_attributes']> | SaveOptions<M['_attributes']>) => HookReturn
): void; ): void;
/** /**
...@@ -2207,13 +2289,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2207,13 +2289,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static afterSave<M extends Model>( public static afterSave<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (instance: M, options: UpdateOptions | SaveOptions) => HookReturn fn: (instance: M, options: UpdateOptions<M['_attributes']> | SaveOptions<M['_attributes']>) => HookReturn
): void; ): void;
public static afterSave<M extends Model>( public static afterSave<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (instance: M, options: UpdateOptions | SaveOptions) => HookReturn fn: (instance: M, options: UpdateOptions<M['_attributes']> | SaveOptions<M['_attributes']>) => HookReturn
): void; ): void;
/** /**
...@@ -2223,13 +2305,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2223,13 +2305,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with instances, options * @param fn A callback function that is called with instances, options
*/ */
public static beforeBulkCreate<M extends Model>( public static beforeBulkCreate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (instances: M[], options: BulkCreateOptions) => HookReturn fn: (instances: M[], options: BulkCreateOptions<M['_attributes']>) => HookReturn
): void; ): void;
public static beforeBulkCreate<M extends Model>( public static beforeBulkCreate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (instances: M[], options: BulkCreateOptions) => HookReturn fn: (instances: M[], options: BulkCreateOptions<M['_attributes']>) => HookReturn
): void; ): void;
/** /**
...@@ -2239,13 +2321,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2239,13 +2321,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with instances, options * @param fn A callback function that is called with instances, options
*/ */
public static afterBulkCreate<M extends Model>( public static afterBulkCreate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (instances: M[], options: BulkCreateOptions) => HookReturn fn: (instances: M[], options: BulkCreateOptions<M['_attributes']>) => HookReturn
): void; ): void;
public static afterBulkCreate<M extends Model>( public static afterBulkCreate<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (instances: M[], options: BulkCreateOptions) => HookReturn fn: (instances: M[], options: BulkCreateOptions<M['_attributes']>) => HookReturn
): void; ): void;
/** /**
...@@ -2254,8 +2336,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2254,8 +2336,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static beforeBulkDestroy(name: string, fn: (options: BulkCreateOptions) => HookReturn): void; public static beforeBulkDestroy<M extends Model>(
public static beforeBulkDestroy(fn: (options: BulkCreateOptions) => HookReturn): void; this: ModelStatic<M>,
name: string, fn: (options: BulkCreateOptions<M['_attributes']>) => HookReturn): void;
public static beforeBulkDestroy<M extends Model>(
this: ModelStatic<M>,
fn: (options: BulkCreateOptions<M['_attributes']>) => HookReturn
): void;
/** /**
* A hook that is run after destroying instances in bulk * A hook that is run after destroying instances in bulk
...@@ -2263,8 +2350,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2263,8 +2350,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static afterBulkDestroy(name: string, fn: (options: DestroyOptions) => HookReturn): void; public static afterBulkDestroy<M extends Model>(
public static afterBulkDestroy(fn: (options: DestroyOptions) => HookReturn): void; this: ModelStatic<M>,
name: string, fn: (options: DestroyOptions<M['_attributes']>) => HookReturn
): void;
public static afterBulkDestroy<M extends Model>(
this: ModelStatic<M>,
fn: (options: DestroyOptions<M['_attributes']>) => HookReturn
): void;
/** /**
* A hook that is run after updating instances in bulk * A hook that is run after updating instances in bulk
...@@ -2272,8 +2365,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2272,8 +2365,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static beforeBulkUpdate(name: string, fn: (options: UpdateOptions) => HookReturn): void; public static beforeBulkUpdate<M extends Model>(
public static beforeBulkUpdate(fn: (options: UpdateOptions) => HookReturn): void; this: ModelStatic<M>,
name: string, fn: (options: UpdateOptions<M['_attributes']>) => HookReturn
): void;
public static beforeBulkUpdate<M extends Model>(
this: ModelStatic<M>,
fn: (options: UpdateOptions<M['_attributes']>) => HookReturn
): void;
/** /**
* A hook that is run after updating instances in bulk * A hook that is run after updating instances in bulk
...@@ -2281,8 +2380,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2281,8 +2380,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static afterBulkUpdate(name: string, fn: (options: UpdateOptions) => HookReturn): void; public static afterBulkUpdate<M extends Model>(
public static afterBulkUpdate(fn: (options: UpdateOptions) => HookReturn): void; this: ModelStatic<M>,
name: string, fn: (options: UpdateOptions<M['_attributes']>) => HookReturn
): void;
public static afterBulkUpdate<M extends Model>(
this: ModelStatic<M>,
fn: (options: UpdateOptions<M['_attributes']>) => HookReturn
): void;
/** /**
* A hook that is run before a find (select) query * A hook that is run before a find (select) query
...@@ -2290,8 +2395,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2290,8 +2395,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static beforeFind(name: string, fn: (options: FindOptions) => HookReturn): void; public static beforeFind<M extends Model>(
public static beforeFind(fn: (options: FindOptions) => HookReturn): void; this: ModelStatic<M>,
name: string, fn: (options: FindOptions<M['_attributes']>) => HookReturn
): void;
public static beforeFind<M extends Model>(
this: ModelStatic<M>,
fn: (options: FindOptions<M['_attributes']>) => HookReturn
): void;
/** /**
* A hook that is run before a count query * A hook that is run before a count query
...@@ -2299,8 +2410,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2299,8 +2410,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static beforeCount(name: string, fn: (options: CountOptions) => HookReturn): void; public static beforeCount<M extends Model>(
public static beforeCount(fn: (options: CountOptions) => HookReturn): void; this: ModelStatic<M>,
name: string, fn: (options: CountOptions<M['_attributes']>) => HookReturn
): void;
public static beforeCount<M extends Model>(
this: ModelStatic<M>,
fn: (options: CountOptions<M['_attributes']>) => HookReturn
): void;
/** /**
* A hook that is run before a find (select) query, after any { include: {all: ...} } options are expanded * A hook that is run before a find (select) query, after any { include: {all: ...} } options are expanded
...@@ -2308,8 +2425,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2308,8 +2425,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static beforeFindAfterExpandIncludeAll(name: string, fn: (options: FindOptions) => HookReturn): void; public static beforeFindAfterExpandIncludeAll<M extends Model>(
public static beforeFindAfterExpandIncludeAll(fn: (options: FindOptions) => HookReturn): void; this: ModelStatic<M>,
name: string, fn: (options: FindOptions<M['_attributes']>) => HookReturn
): void;
public static beforeFindAfterExpandIncludeAll<M extends Model>(
this: ModelStatic<M>,
fn: (options: FindOptions<M['_attributes']>) => HookReturn
): void;
/** /**
* A hook that is run before a find (select) query, after all option parsing is complete * A hook that is run before a find (select) query, after all option parsing is complete
...@@ -2317,8 +2440,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2317,8 +2440,14 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static beforeFindAfterOptions(name: string, fn: (options: FindOptions) => HookReturn): void; public static beforeFindAfterOptions<M extends Model>(
public static beforeFindAfterOptions(fn: (options: FindOptions) => void): HookReturn; this: ModelStatic<M>,
name: string, fn: (options: FindOptions<M['_attributes']>) => HookReturn
): void;
public static beforeFindAfterOptions<M extends Model>(
this: ModelStatic<M>,
fn: (options: FindOptions<M['_attributes']>) => void
): HookReturn;
/** /**
* A hook that is run after a find (select) query * A hook that is run after a find (select) query
...@@ -2327,13 +2456,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2327,13 +2456,13 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param fn A callback function that is called with instance(s), options * @param fn A callback function that is called with instance(s), options
*/ */
public static afterFind<M extends Model>( public static afterFind<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
name: string, name: string,
fn: (instancesOrInstance: M[] | M | null, options: FindOptions) => HookReturn fn: (instancesOrInstance: M[] | M | null, options: FindOptions<M['_attributes']>) => HookReturn
): void; ): void;
public static afterFind<M extends Model>( public static afterFind<M extends Model>(
this: { new(): M } & typeof Model, this: ModelStatic<M>,
fn: (instancesOrInstance: M[] | M | null, options: FindOptions) => HookReturn fn: (instancesOrInstance: M[] | M | null, options: FindOptions<M['_attributes']>) => HookReturn
): void; ): void;
/** /**
...@@ -2374,7 +2503,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2374,7 +2503,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param options Options for the association * @param options Options for the association
*/ */
public static hasOne<M extends Model, T extends Model>( public static hasOne<M extends Model, T extends Model>(
this: ModelCtor<M>, target: ModelCtor<T>, options?: HasOneOptions this: ModelStatic<M>, target: ModelStatic<T>, options?: HasOneOptions
): HasOne<M, T>; ): HasOne<M, T>;
/** /**
...@@ -2387,7 +2516,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2387,7 +2516,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param options Options for the association * @param options Options for the association
*/ */
public static belongsTo<M extends Model, T extends Model>( public static belongsTo<M extends Model, T extends Model>(
this: ModelCtor<M>, target: ModelCtor<T>, options?: BelongsToOptions this: ModelStatic<M>, target: ModelStatic<T>, options?: BelongsToOptions
): BelongsTo<M, T>; ): BelongsTo<M, T>;
/** /**
...@@ -2434,16 +2563,17 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2434,16 +2563,17 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* Similarily, when fetching through a join table with custom attributes, these attributes will be * Similarily, when fetching through a join table with custom attributes, these attributes will be
* available as an object with the name of the through model. * available as an object with the name of the through model.
* ```js * ```js
* const projects = await user.getProjects(); * user.getProjects().then(projects => {
* const p1 = projects[0]; * const p1 = projects[0]
* p1.UserProjects.started // Is this project started yet? * p1.userprojects.started // Is this project started yet?
* })
* ``` * ```
* *
* @param target The model that will be associated with hasOne relationship * @param target The model that will be associated with hasOne relationship
* @param options Options for the association * @param options Options for the association
*/ */
public static hasMany<M extends Model, T extends Model>( public static hasMany<M extends Model, T extends Model>(
this: ModelCtor<M>, target: ModelCtor<T>, options?: HasManyOptions this: ModelStatic<M>, target: ModelStatic<T>, options?: HasManyOptions
): HasMany<M, T>; ): HasMany<M, T>;
/** /**
...@@ -2485,9 +2615,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2485,9 +2615,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* Similarily, when fetching through a join table with custom attributes, these attributes will be * Similarily, when fetching through a join table with custom attributes, these attributes will be
* available as an object with the name of the through model. * available as an object with the name of the through model.
* ```js * ```js
* const porjects = await user.getProjects(); * user.getProjects().then(projects => {
* const p1 = projects[0]; * const p1 = projects[0]
* p1.userprojects.started // Is this project started yet? * p1.userprojects.started // Is this project started yet?
* })
* ``` * ```
* *
* @param target The model that will be associated with hasOne relationship * @param target The model that will be associated with hasOne relationship
...@@ -2495,7 +2626,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2495,7 +2626,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* *
*/ */
public static belongsToMany<M extends Model, T extends Model>( public static belongsToMany<M extends Model, T extends Model>(
this: ModelCtor<M>, target: ModelCtor<T>, options: BelongsToManyOptions this: ModelStatic<M>, target: ModelStatic<T>, options: BelongsToManyOptions
): BelongsToMany<M, T>; ): BelongsToMany<M, T>;
/** /**
...@@ -2512,7 +2643,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2512,7 +2643,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* Builds a new model instance. * Builds a new model instance.
* @param values an object of key value pairs * @param values an object of key value pairs
*/ */
constructor(values?: object, options?: BuildOptions); constructor(values?: TCreationAttributes, options?: BuildOptions);
/** /**
* Get an object representing the query for this instance, use with `options.where` * Get an object representing the query for this instance, use with `options.where`
...@@ -2522,12 +2653,12 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2522,12 +2653,12 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
/** /**
* Get the value of the underlying data value * Get the value of the underlying data value
*/ */
public getDataValue<K extends keyof this>(key: K): this[K]; public getDataValue<K extends keyof TModelAttributes>(key: K): TModelAttributes[K];
/** /**
* Update the underlying data value * Update the underlying data value
*/ */
public setDataValue<K extends keyof this>(key: K, value: this[K]): void; public setDataValue<K extends keyof TModelAttributes>(key: K, value: TModelAttributes[K]): void;
/** /**
* If no key is given, returns all values of the instance, also invoking virtual getters. * If no key is given, returns all values of the instance, also invoking virtual getters.
...@@ -2537,7 +2668,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2537,7 +2668,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* *
* @param options.plain If set to true, included instances will be returned as plain objects * @param options.plain If set to true, included instances will be returned as plain objects
*/ */
public get(options?: { plain?: boolean; clone?: boolean }): object; public get(options?: { plain?: boolean; clone?: boolean }): TModelAttributes;
public get<K extends keyof this>(key: K, options?: { plain?: boolean; clone?: boolean }): this[K]; public get<K extends keyof this>(key: K, options?: { plain?: boolean; clone?: boolean }): this[K];
public get(key: string, options?: { plain?: boolean; clone?: boolean }): unknown; public get(key: string, options?: { plain?: boolean; clone?: boolean }): unknown;
...@@ -2565,10 +2696,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2565,10 +2696,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param options.raw If set to true, field and virtual setters will be ignored * @param options.raw If set to true, field and virtual setters will be ignored
* @param options.reset Clear all previously set data values * @param options.reset Clear all previously set data values
*/ */
public set<K extends keyof this>(key: K, value: this[K], options?: SetOptions): this; public set<K extends keyof TModelAttributes>(key: K, value: TModelAttributes[K], options?: SetOptions): this;
public set(keys: Partial<this>, options?: SetOptions): this; public set(keys: Partial<TModelAttributes>, options?: SetOptions): this;
public setAttributes<K extends keyof this>(key: K, value: this[K], options?: SetOptions): this; public setAttributes<K extends keyof TModelAttributes>(key: K, value: TModelAttributes[K], options?: SetOptions): this;
public setAttributes(keys: object, options?: SetOptions): this; public setAttributes(keys: Partial<TModelAttributes>, options?: SetOptions): this;
/** /**
* If changed is called with a string it will return a boolean indicating whether the value of that key in * If changed is called with a string it will return a boolean indicating whether the value of that key in
...@@ -2598,7 +2729,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2598,7 +2729,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* *
* This method is not aware of eager loaded associations. In other words, if some other model instance (child) was eager loaded with this instance (parent), and you change something in the child, calling `save()` will simply ignore the change that happened on the child. * This method is not aware of eager loaded associations. In other words, if some other model instance (child) was eager loaded with this instance (parent), and you change something in the child, calling `save()` will simply ignore the change that happened on the child.
*/ */
public save(options?: SaveOptions): Promise<this>; public save(options?: SaveOptions<TModelAttributes>): Promise<this>;
/** /**
* Refresh the current instance in-place, i.e. update the object with current data from the DB and return * Refresh the current instance in-place, i.e. update the object with current data from the DB and return
...@@ -2606,7 +2737,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2606,7 +2737,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* return a new instance. With this method, all references to the Instance are updated with the new data * return a new instance. With this method, all references to the Instance are updated with the new data
* and no new objects are created. * and no new objects are created.
*/ */
public reload(options?: FindOptions): Promise<this>; public reload(options?: FindOptions<TModelAttributes>): Promise<this>;
/** /**
* Validate the attribute of this instance according to validation rules set in the model definition. * Validate the attribute of this instance according to validation rules set in the model definition.
...@@ -2621,8 +2752,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2621,8 +2752,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
/** /**
* This is the same as calling `set` and then calling `save`. * This is the same as calling `set` and then calling `save`.
*/ */
public update<K extends keyof this>(key: K, value: this[K], options?: InstanceUpdateOptions): Promise<this>; public update<K extends keyof this>(key: K, value: this[K], options?: InstanceUpdateOptions<TModelAttributes>): Promise<this>;
public update(keys: object, options?: InstanceUpdateOptions): Promise<this>; public update(keys: object, options?: InstanceUpdateOptions<TModelAttributes>): Promise<this>;
/** /**
* Destroy the row corresponding to this instance. Depending on your setting for paranoid, the row will * Destroy the row corresponding to this instance. Depending on your setting for paranoid, the row will
...@@ -2655,9 +2786,9 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2655,9 +2786,9 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* If an array is provided, the same is true for each column. * If an array is provided, the same is true for each column.
* If and object is provided, each column is incremented by the value given. * If and object is provided, each column is incremented by the value given.
*/ */
public increment<K extends keyof this>( public increment<K extends keyof TModelAttributes>(
fields: K | K[] | Partial<this>, fields: K | K[] | Partial<TModelAttributes>,
options?: IncrementDecrementOptionsWithBy options?: IncrementDecrementOptionsWithBy<TModelAttributes>
): Promise<this>; ): Promise<this>;
/** /**
...@@ -2680,9 +2811,9 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2680,9 +2811,9 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* If an array is provided, the same is true for each column. * If an array is provided, the same is true for each column.
* If and object is provided, each column is decremented by the value given * If and object is provided, each column is decremented by the value given
*/ */
public decrement<K extends keyof this>( public decrement<K extends keyof TModelAttributes>(
fields: K | K[] | Partial<this>, fields: K | K[] | Partial<TModelAttributes>,
options?: IncrementDecrementOptionsWithBy options?: IncrementDecrementOptionsWithBy<TModelAttributes>
): Promise<this>; ): Promise<this>;
/** /**
...@@ -2713,6 +2844,11 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2713,6 +2844,11 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
export type ModelType = typeof Model; export type ModelType = typeof Model;
export type ModelCtor<M extends Model> = { new(): M } & ModelType; // Do not switch the order of `typeof Model` and `{ new(): M }`. For
// instances created by `sequelize.define` to typecheck well, `typeof Model`
// must come first for unknown reasons.
export type ModelCtor<M extends Model> = typeof Model & { new(): M };
export type ModelStatic<M extends Model> = { new(): M };
export default Model; export default Model;
import { DataType } from './data-types'; import { DataType } from './data-types';
import { Logging, Model, ModelAttributeColumnOptions, ModelAttributes, Transactionable, WhereOptions, Filterable, Poolable } from './model'; import {
Logging,
Model,
ModelAttributeColumnOptions,
ModelAttributes,
Transactionable,
WhereOptions,
Filterable,
Poolable,
ModelCtor, ModelStatic
} from './model';
import QueryTypes = require('./query-types'); import QueryTypes = require('./query-types');
import { Sequelize, RetryOptions } from './sequelize'; import { Sequelize, RetryOptions } from './sequelize';
import { Transaction } from './transaction'; import { Transaction } from './transaction';
...@@ -71,15 +81,15 @@ export interface QueryOptions extends Logging, Transactionable, Poolable { ...@@ -71,15 +81,15 @@ export interface QueryOptions extends Logging, Transactionable, Poolable {
fieldMap?: FieldMap; fieldMap?: FieldMap;
} }
export interface QueryOptionsWithWhere extends QueryOptions, Filterable { export interface QueryOptionsWithWhere extends QueryOptions, Filterable<any> {
} }
export interface QueryOptionsWithModel extends QueryOptions { export interface QueryOptionsWithModel<M extends Model> extends QueryOptions {
/** /**
* A sequelize model used to build the returned model instances (used to be called callee) * A sequelize model used to build the returned model instances (used to be called callee)
*/ */
model: typeof Model; model: ModelStatic<M>;
} }
export interface QueryOptionsWithType<T extends QueryTypes> extends QueryOptions { export interface QueryOptionsWithType<T extends QueryTypes> extends QueryOptions {
...@@ -189,7 +199,7 @@ export interface IndexesOptions { ...@@ -189,7 +199,7 @@ export interface IndexesOptions {
/** /**
* Optional where parameter for index. Can be used to limit the index to certain rows. * Optional where parameter for index. Can be used to limit the index to certain rows.
*/ */
where?: WhereOptions; where?: WhereOptions<any>;
/** /**
* Prefix to append to the index name. * Prefix to append to the index name.
...@@ -215,7 +225,7 @@ export interface AddDefaultConstraintOptions extends BaseConstraintOptions { ...@@ -215,7 +225,7 @@ export interface AddDefaultConstraintOptions extends BaseConstraintOptions {
export interface AddCheckConstraintOptions extends BaseConstraintOptions { export interface AddCheckConstraintOptions extends BaseConstraintOptions {
type: 'check'; type: 'check';
where?: WhereOptions; where?: WhereOptions<any>;
} }
export interface AddPrimaryKeyConstraintOptions extends BaseConstraintOptions { export interface AddPrimaryKeyConstraintOptions extends BaseConstraintOptions {
...@@ -321,9 +331,9 @@ export class QueryInterface { ...@@ -321,9 +331,9 @@ export class QueryInterface {
* @param attributes Hash of attributes, key is attribute name, value is data type * @param attributes Hash of attributes, key is attribute name, value is data type
* @param options Table options. * @param options Table options.
*/ */
public createTable( public createTable<M extends Model>(
tableName: string | { schema?: string; tableName?: string }, tableName: string | { schema?: string; tableName?: string },
attributes: ModelAttributes, attributes: ModelAttributes<M, M['_creationAttributes']>,
options?: QueryInterfaceCreateTableOptions options?: QueryInterfaceCreateTableOptions
): Promise<void>; ): Promise<void>;
...@@ -490,11 +500,11 @@ export class QueryInterface { ...@@ -490,11 +500,11 @@ export class QueryInterface {
/** /**
* Updates a row * Updates a row
*/ */
public update( public update<M extends Model>(
instance: Model, instance: M,
tableName: TableName, tableName: TableName,
values: object, values: object,
identifier: WhereOptions, identifier: WhereOptions<M['_attributes']>,
options?: QueryOptions options?: QueryOptions
): Promise<object>; ): Promise<object>;
...@@ -504,7 +514,7 @@ export class QueryInterface { ...@@ -504,7 +514,7 @@ export class QueryInterface {
public bulkUpdate( public bulkUpdate(
tableName: TableName, tableName: TableName,
values: object, values: object,
identifier: WhereOptions, identifier: WhereOptions<any>,
options?: QueryOptions, options?: QueryOptions,
attributes?: string[] | string attributes?: string[] | string
): Promise<object>; ): Promise<object>;
...@@ -512,14 +522,19 @@ export class QueryInterface { ...@@ -512,14 +522,19 @@ export class QueryInterface {
/** /**
* Deletes a row * Deletes a row
*/ */
public delete(instance: Model | null, tableName: TableName, identifier: WhereOptions, options?: QueryOptions): Promise<object>; public delete(
instance: Model | null,
tableName: TableName,
identifier: WhereOptions<any>,
options?: QueryOptions
): Promise<object>;
/** /**
* Deletes multiple rows at once * Deletes multiple rows at once
*/ */
public bulkDelete( public bulkDelete(
tableName: TableName, tableName: TableName,
identifier: WhereOptions, identifier: WhereOptions<any>,
options?: QueryOptions, options?: QueryOptions,
model?: typeof Model model?: typeof Model
): Promise<object>; ): Promise<object>;
...@@ -532,11 +547,11 @@ export class QueryInterface { ...@@ -532,11 +547,11 @@ export class QueryInterface {
/** /**
* Increments a row value * Increments a row value
*/ */
public increment( public increment<M extends Model>(
instance: Model, instance: Model,
tableName: TableName, tableName: TableName,
values: object, values: object,
identifier: WhereOptions, identifier: WhereOptions<M['_attributes']>,
options?: QueryOptions options?: QueryOptions
): Promise<object>; ): Promise<object>;
......
...@@ -371,7 +371,7 @@ export interface Options extends Logging { ...@@ -371,7 +371,7 @@ export interface Options extends Logging {
/** /**
* Sets global permanent hooks. * Sets global permanent hooks.
*/ */
hooks?: Partial<SequelizeHooks>; hooks?: Partial<SequelizeHooks<Model, any, any>>;
/** /**
* Set to `true` to automatically minify aliases generated by sequelize. * Set to `true` to automatically minify aliases generated by sequelize.
...@@ -517,8 +517,8 @@ export class Sequelize extends Hooks { ...@@ -517,8 +517,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with attributes, options * @param fn A callback function that is called with attributes, options
*/ */
public static beforeCreate(name: string, fn: (attributes: Model, options: CreateOptions) => void): void; public static beforeCreate(name: string, fn: (attributes: Model, options: CreateOptions<any>) => void): void;
public static beforeCreate(fn: (attributes: Model, options: CreateOptions) => void): void; public static beforeCreate(fn: (attributes: Model, options: CreateOptions<any>) => void): void;
/** /**
* A hook that is run after creating a single instance * A hook that is run after creating a single instance
...@@ -526,8 +526,8 @@ export class Sequelize extends Hooks { ...@@ -526,8 +526,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with attributes, options * @param fn A callback function that is called with attributes, options
*/ */
public static afterCreate(name: string, fn: (attributes: Model, options: CreateOptions) => void): void; public static afterCreate(name: string, fn: (attributes: Model, options: CreateOptions<any>) => void): void;
public static afterCreate(fn: (attributes: Model, options: CreateOptions) => void): void; public static afterCreate(fn: (attributes: Model, options: CreateOptions<any>) => void): void;
/** /**
* A hook that is run before destroying a single instance * A hook that is run before destroying a single instance
...@@ -553,8 +553,8 @@ export class Sequelize extends Hooks { ...@@ -553,8 +553,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static beforeUpdate(name: string, fn: (instance: Model, options: UpdateOptions) => void): void; public static beforeUpdate(name: string, fn: (instance: Model, options: UpdateOptions<any>) => void): void;
public static beforeUpdate(fn: (instance: Model, options: UpdateOptions) => void): void; public static beforeUpdate(fn: (instance: Model, options: UpdateOptions<any>) => void): void;
/** /**
* A hook that is run after updating a single instance * A hook that is run after updating a single instance
...@@ -562,8 +562,8 @@ export class Sequelize extends Hooks { ...@@ -562,8 +562,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static afterUpdate(name: string, fn: (instance: Model, options: UpdateOptions) => void): void; public static afterUpdate(name: string, fn: (instance: Model, options: UpdateOptions<any>) => void): void;
public static afterUpdate(fn: (instance: Model, options: UpdateOptions) => void): void; public static afterUpdate(fn: (instance: Model, options: UpdateOptions<any>) => void): void;
/** /**
* A hook that is run before creating or updating a single instance, It proxies `beforeCreate` and `beforeUpdate` * A hook that is run before creating or updating a single instance, It proxies `beforeCreate` and `beforeUpdate`
...@@ -571,8 +571,11 @@ export class Sequelize extends Hooks { ...@@ -571,8 +571,11 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static beforeSave(name: string, fn: (instance: Model, options: UpdateOptions | CreateOptions) => void): void; public static beforeSave(
public static beforeSave(fn: (instance: Model, options: UpdateOptions | CreateOptions) => void): void; name: string,
fn: (instance: Model, options: UpdateOptions<any> | CreateOptions<any>) => void
): void;
public static beforeSave(fn: (instance: Model, options: UpdateOptions<any> | CreateOptions<any>) => void): void;
/** /**
* A hook that is run after creating or updating a single instance, It proxies `afterCreate` and `afterUpdate` * A hook that is run after creating or updating a single instance, It proxies `afterCreate` and `afterUpdate`
...@@ -580,8 +583,13 @@ export class Sequelize extends Hooks { ...@@ -580,8 +583,13 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public static afterSave(name: string, fn: (instance: Model, options: UpdateOptions | CreateOptions) => void): void; public static afterSave(
public static afterSave(fn: (instance: Model, options: UpdateOptions | CreateOptions) => void): void; name: string,
fn: (instance: Model, options: UpdateOptions<any> | CreateOptions<any>) => void
): void;
public static afterSave(
fn: (instance: Model, options: UpdateOptions<any> | CreateOptions<any>) => void
): void;
/** /**
* A hook that is run before creating instances in bulk * A hook that is run before creating instances in bulk
...@@ -589,8 +597,11 @@ export class Sequelize extends Hooks { ...@@ -589,8 +597,11 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with instances, options * @param fn A callback function that is called with instances, options
*/ */
public static beforeBulkCreate(name: string, fn: (instances: Model[], options: BulkCreateOptions) => void): void; public static beforeBulkCreate(
public static beforeBulkCreate(fn: (instances: Model[], options: BulkCreateOptions) => void): void; name: string,
fn: (instances: Model[], options: BulkCreateOptions<any>) => void
): void;
public static beforeBulkCreate(fn: (instances: Model[], options: BulkCreateOptions<any>) => void): void;
/** /**
* A hook that is run after creating instances in bulk * A hook that is run after creating instances in bulk
...@@ -598,8 +609,10 @@ export class Sequelize extends Hooks { ...@@ -598,8 +609,10 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with instances, options * @param fn A callback function that is called with instances, options
*/ */
public static afterBulkCreate(name: string, fn: (instances: Model[], options: BulkCreateOptions) => void): void; public static afterBulkCreate(
public static afterBulkCreate(fn: (instances: Model[], options: BulkCreateOptions) => void): void; name: string, fn: (instances: Model[], options: BulkCreateOptions<any>) => void
): void;
public static afterBulkCreate(fn: (instances: Model[], options: BulkCreateOptions<any>) => void): void;
/** /**
* A hook that is run before destroying instances in bulk * A hook that is run before destroying instances in bulk
...@@ -607,8 +620,8 @@ export class Sequelize extends Hooks { ...@@ -607,8 +620,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static beforeBulkDestroy(name: string, fn: (options: BulkCreateOptions) => void): void; public static beforeBulkDestroy(name: string, fn: (options: BulkCreateOptions<any>) => void): void;
public static beforeBulkDestroy(fn: (options: BulkCreateOptions) => void): void; public static beforeBulkDestroy(fn: (options: BulkCreateOptions<any>) => void): void;
/** /**
* A hook that is run after destroying instances in bulk * A hook that is run after destroying instances in bulk
...@@ -616,8 +629,8 @@ export class Sequelize extends Hooks { ...@@ -616,8 +629,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static afterBulkDestroy(name: string, fn: (options: DestroyOptions) => void): void; public static afterBulkDestroy(name: string, fn: (options: DestroyOptions<any>) => void): void;
public static afterBulkDestroy(fn: (options: DestroyOptions) => void): void; public static afterBulkDestroy(fn: (options: DestroyOptions<any>) => void): void;
/** /**
* A hook that is run after updating instances in bulk * A hook that is run after updating instances in bulk
...@@ -625,8 +638,8 @@ export class Sequelize extends Hooks { ...@@ -625,8 +638,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static beforeBulkUpdate(name: string, fn: (options: UpdateOptions) => void): void; public static beforeBulkUpdate(name: string, fn: (options: UpdateOptions<any>) => void): void;
public static beforeBulkUpdate(fn: (options: UpdateOptions) => void): void; public static beforeBulkUpdate(fn: (options: UpdateOptions<any>) => void): void;
/** /**
* A hook that is run after updating instances in bulk * A hook that is run after updating instances in bulk
...@@ -634,8 +647,8 @@ export class Sequelize extends Hooks { ...@@ -634,8 +647,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static afterBulkUpdate(name: string, fn: (options: UpdateOptions) => void): void; public static afterBulkUpdate(name: string, fn: (options: UpdateOptions<any>) => void): void;
public static afterBulkUpdate(fn: (options: UpdateOptions) => void): void; public static afterBulkUpdate(fn: (options: UpdateOptions<any>) => void): void;
/** /**
* A hook that is run before a find (select) query * A hook that is run before a find (select) query
...@@ -643,8 +656,8 @@ export class Sequelize extends Hooks { ...@@ -643,8 +656,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static beforeFind(name: string, fn: (options: FindOptions) => void): void; public static beforeFind(name: string, fn: (options: FindOptions<any>) => void): void;
public static beforeFind(fn: (options: FindOptions) => void): void; public static beforeFind(fn: (options: FindOptions<any>) => void): void;
/** /**
* A hook that is run before a connection is established * A hook that is run before a connection is established
...@@ -688,8 +701,8 @@ export class Sequelize extends Hooks { ...@@ -688,8 +701,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static beforeFindAfterExpandIncludeAll(name: string, fn: (options: FindOptions) => void): void; public static beforeFindAfterExpandIncludeAll(name: string, fn: (options: FindOptions<any>) => void): void;
public static beforeFindAfterExpandIncludeAll(fn: (options: FindOptions) => void): void; public static beforeFindAfterExpandIncludeAll(fn: (options: FindOptions<any>) => void): void;
/** /**
* A hook that is run before a find (select) query, after all option parsing is complete * A hook that is run before a find (select) query, after all option parsing is complete
...@@ -697,8 +710,8 @@ export class Sequelize extends Hooks { ...@@ -697,8 +710,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public static beforeFindAfterOptions(name: string, fn: (options: FindOptions) => void): void; public static beforeFindAfterOptions(name: string, fn: (options: FindOptions<any>) => void): void;
public static beforeFindAfterOptions(fn: (options: FindOptions) => void): void; public static beforeFindAfterOptions(fn: (options: FindOptions<any>) => void): void;
/** /**
* A hook that is run after a find (select) query * A hook that is run after a find (select) query
...@@ -708,10 +721,10 @@ export class Sequelize extends Hooks { ...@@ -708,10 +721,10 @@ export class Sequelize extends Hooks {
*/ */
public static afterFind( public static afterFind(
name: string, name: string,
fn: (instancesOrInstance: Model[] | Model | null, options: FindOptions) => void fn: (instancesOrInstance: Model[] | Model | null, options: FindOptions<any>) => void
): void; ): void;
public static afterFind( public static afterFind(
fn: (instancesOrInstance: Model[] | Model | null, options: FindOptions) => void fn: (instancesOrInstance: Model[] | Model | null, options: FindOptions<any>) => void
): void; ): void;
/** /**
...@@ -722,10 +735,10 @@ export class Sequelize extends Hooks { ...@@ -722,10 +735,10 @@ export class Sequelize extends Hooks {
*/ */
public static beforeDefine<M extends Model>( public static beforeDefine<M extends Model>(
name: string, name: string,
fn: (attributes: ModelAttributes, options: ModelOptions<M>) => void fn: (attributes: ModelAttributes<M, M['_creationAttributes']>, options: ModelOptions<M>) => void
): void; ): void;
public static beforeDefine<M extends Model>( public static beforeDefine<M extends Model>(
fn: (attributes: ModelAttributes, options: ModelOptions<M>) => void fn: (attributes: ModelAttributes<M, M['_creationAttributes']>, options: ModelOptions<M>) => void
): void; ): void;
/** /**
...@@ -877,8 +890,8 @@ export class Sequelize extends Hooks { ...@@ -877,8 +890,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with attributes, options * @param fn A callback function that is called with attributes, options
*/ */
public beforeCreate(name: string, fn: (attributes: Model, options: CreateOptions) => void): void; public beforeCreate(name: string, fn: (attributes: Model, options: CreateOptions<any>) => void): void;
public beforeCreate(fn: (attributes: Model, options: CreateOptions) => void): void; public beforeCreate(fn: (attributes: Model, options: CreateOptions<any>) => void): void;
/** /**
* A hook that is run after creating a single instance * A hook that is run after creating a single instance
...@@ -886,8 +899,8 @@ export class Sequelize extends Hooks { ...@@ -886,8 +899,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with attributes, options * @param fn A callback function that is called with attributes, options
*/ */
public afterCreate(name: string, fn: (attributes: Model, options: CreateOptions) => void): void; public afterCreate(name: string, fn: (attributes: Model, options: CreateOptions<any>) => void): void;
public afterCreate(fn: (attributes: Model, options: CreateOptions) => void): void; public afterCreate(fn: (attributes: Model, options: CreateOptions<any>) => void): void;
/** /**
* A hook that is run before destroying a single instance * A hook that is run before destroying a single instance
...@@ -913,8 +926,8 @@ export class Sequelize extends Hooks { ...@@ -913,8 +926,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public beforeUpdate(name: string, fn: (instance: Model, options: UpdateOptions) => void): void; public beforeUpdate(name: string, fn: (instance: Model, options: UpdateOptions<any>) => void): void;
public beforeUpdate(fn: (instance: Model, options: UpdateOptions) => void): void; public beforeUpdate(fn: (instance: Model, options: UpdateOptions<any>) => void): void;
/** /**
* A hook that is run after updating a single instance * A hook that is run after updating a single instance
...@@ -922,8 +935,8 @@ export class Sequelize extends Hooks { ...@@ -922,8 +935,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with instance, options * @param fn A callback function that is called with instance, options
*/ */
public afterUpdate(name: string, fn: (instance: Model, options: UpdateOptions) => void): void; public afterUpdate(name: string, fn: (instance: Model, options: UpdateOptions<any>) => void): void;
public afterUpdate(fn: (instance: Model, options: UpdateOptions) => void): void; public afterUpdate(fn: (instance: Model, options: UpdateOptions<any>) => void): void;
/** /**
* A hook that is run before creating instances in bulk * A hook that is run before creating instances in bulk
...@@ -931,8 +944,8 @@ export class Sequelize extends Hooks { ...@@ -931,8 +944,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with instances, options * @param fn A callback function that is called with instances, options
*/ */
public beforeBulkCreate(name: string, fn: (instances: Model[], options: BulkCreateOptions) => void): void; public beforeBulkCreate(name: string, fn: (instances: Model[], options: BulkCreateOptions<any>) => void): void;
public beforeBulkCreate(fn: (instances: Model[], options: BulkCreateOptions) => void): void; public beforeBulkCreate(fn: (instances: Model[], options: BulkCreateOptions<any>) => void): void;
/** /**
* A hook that is run after creating instances in bulk * A hook that is run after creating instances in bulk
...@@ -940,8 +953,8 @@ export class Sequelize extends Hooks { ...@@ -940,8 +953,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with instances, options * @param fn A callback function that is called with instances, options
*/ */
public afterBulkCreate(name: string, fn: (instances: Model[], options: BulkCreateOptions) => void): void; public afterBulkCreate(name: string, fn: (instances: Model[], options: BulkCreateOptions<any>) => void): void;
public afterBulkCreate(fn: (instances: Model[], options: BulkCreateOptions) => void): void; public afterBulkCreate(fn: (instances: Model[], options: BulkCreateOptions<any>) => void): void;
/** /**
* A hook that is run before destroying instances in bulk * A hook that is run before destroying instances in bulk
...@@ -949,8 +962,8 @@ export class Sequelize extends Hooks { ...@@ -949,8 +962,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public beforeBulkDestroy(name: string, fn: (options: BulkCreateOptions) => void): void; public beforeBulkDestroy(name: string, fn: (options: BulkCreateOptions<any>) => void): void;
public beforeBulkDestroy(fn: (options: BulkCreateOptions) => void): void; public beforeBulkDestroy(fn: (options: BulkCreateOptions<any>) => void): void;
/** /**
* A hook that is run after destroying instances in bulk * A hook that is run after destroying instances in bulk
...@@ -958,8 +971,8 @@ export class Sequelize extends Hooks { ...@@ -958,8 +971,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public afterBulkDestroy(name: string, fn: (options: DestroyOptions) => void): void; public afterBulkDestroy(name: string, fn: (options: DestroyOptions<any>) => void): void;
public afterBulkDestroy(fn: (options: DestroyOptions) => void): void; public afterBulkDestroy(fn: (options: DestroyOptions<any>) => void): void;
/** /**
* A hook that is run after updating instances in bulk * A hook that is run after updating instances in bulk
...@@ -967,8 +980,8 @@ export class Sequelize extends Hooks { ...@@ -967,8 +980,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public beforeBulkUpdate(name: string, fn: (options: UpdateOptions) => void): void; public beforeBulkUpdate(name: string, fn: (options: UpdateOptions<any>) => void): void;
public beforeBulkUpdate(fn: (options: UpdateOptions) => void): void; public beforeBulkUpdate(fn: (options: UpdateOptions<any>) => void): void;
/** /**
* A hook that is run after updating instances in bulk * A hook that is run after updating instances in bulk
...@@ -976,8 +989,8 @@ export class Sequelize extends Hooks { ...@@ -976,8 +989,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public afterBulkUpdate(name: string, fn: (options: UpdateOptions) => void): void; public afterBulkUpdate(name: string, fn: (options: UpdateOptions<any>) => void): void;
public afterBulkUpdate(fn: (options: UpdateOptions) => void): void; public afterBulkUpdate(fn: (options: UpdateOptions<any>) => void): void;
/** /**
* A hook that is run before a find (select) query * A hook that is run before a find (select) query
...@@ -985,8 +998,8 @@ export class Sequelize extends Hooks { ...@@ -985,8 +998,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public beforeFind(name: string, fn: (options: FindOptions) => void): void; public beforeFind(name: string, fn: (options: FindOptions<any>) => void): void;
public beforeFind(fn: (options: FindOptions) => void): void; public beforeFind(fn: (options: FindOptions<any>) => void): void;
/** /**
* A hook that is run before a find (select) query, after any { include: {all: ...} } options are expanded * A hook that is run before a find (select) query, after any { include: {all: ...} } options are expanded
...@@ -994,8 +1007,8 @@ export class Sequelize extends Hooks { ...@@ -994,8 +1007,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public beforeFindAfterExpandIncludeAll(name: string, fn: (options: FindOptions) => void): void; public beforeFindAfterExpandIncludeAll(name: string, fn: (options: FindOptions<any>) => void): void;
public beforeFindAfterExpandIncludeAll(fn: (options: FindOptions) => void): void; public beforeFindAfterExpandIncludeAll(fn: (options: FindOptions<any>) => void): void;
/** /**
* A hook that is run before a find (select) query, after all option parsing is complete * A hook that is run before a find (select) query, after all option parsing is complete
...@@ -1003,8 +1016,8 @@ export class Sequelize extends Hooks { ...@@ -1003,8 +1016,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with options * @param fn A callback function that is called with options
*/ */
public beforeFindAfterOptions(name: string, fn: (options: FindOptions) => void): void; public beforeFindAfterOptions(name: string, fn: (options: FindOptions<any>) => void): void;
public beforeFindAfterOptions(fn: (options: FindOptions) => void): void; public beforeFindAfterOptions(fn: (options: FindOptions<any>) => void): void;
/** /**
* A hook that is run after a find (select) query * A hook that is run after a find (select) query
...@@ -1014,9 +1027,9 @@ export class Sequelize extends Hooks { ...@@ -1014,9 +1027,9 @@ export class Sequelize extends Hooks {
*/ */
public afterFind( public afterFind(
name: string, name: string,
fn: (instancesOrInstance: Model[] | Model | null, options: FindOptions) => void fn: (instancesOrInstance: Model[] | Model | null, options: FindOptions<any>) => void
): void; ): void;
public afterFind(fn: (instancesOrInstance: Model[] | Model | null, options: FindOptions) => void): void; public afterFind(fn: (instancesOrInstance: Model[] | Model | null, options: FindOptions<any>) => void): void;
/** /**
* A hook that is run before a define call * A hook that is run before a define call
...@@ -1024,8 +1037,8 @@ export class Sequelize extends Hooks { ...@@ -1024,8 +1037,8 @@ export class Sequelize extends Hooks {
* @param name * @param name
* @param fn A callback function that is called with attributes, options * @param fn A callback function that is called with attributes, options
*/ */
public beforeDefine(name: string, fn: (attributes: ModelAttributes, options: ModelOptions) => void): void; public beforeDefine(name: string, fn: (attributes: ModelAttributes<Model, any>, options: ModelOptions) => void): void;
public beforeDefine(fn: (attributes: ModelAttributes, options: ModelOptions) => void): void; public beforeDefine(fn: (attributes: ModelAttributes<Model, any>, options: ModelOptions) => void): void;
/** /**
* A hook that is run after a define call * A hook that is run after a define call
...@@ -1151,7 +1164,11 @@ export class Sequelize extends Hooks { ...@@ -1151,7 +1164,11 @@ export class Sequelize extends Hooks {
* @param options These options are merged with the default define options provided to the Sequelize * @param options These options are merged with the default define options provided to the Sequelize
* constructor * constructor
*/ */
public define(modelName: string, attributes: ModelAttributes, options?: ModelOptions): typeof Model; public define<M extends Model, TCreationAttributes = M['_creationAttributes']>(
modelName: string,
attributes: ModelAttributes<M, TCreationAttributes>,
options?: ModelOptions
): ModelCtor<M>;
/** /**
* Fetch a Model which is already defined * Fetch a Model which is already defined
...@@ -1216,7 +1233,7 @@ export class Sequelize extends Hooks { ...@@ -1216,7 +1233,7 @@ export class Sequelize extends Hooks {
public query(sql: string | { query: string; values: unknown[] }, options: QueryOptionsWithType<QueryTypes.DESCRIBE>): Promise<ColumnsDescription>; public query(sql: string | { query: string; values: unknown[] }, options: QueryOptionsWithType<QueryTypes.DESCRIBE>): Promise<ColumnsDescription>;
public query<M extends Model>( public query<M extends Model>(
sql: string | { query: string; values: unknown[] }, sql: string | { query: string; values: unknown[] },
options: QueryOptionsWithModel options: QueryOptionsWithModel<M>
): Promise<M[]>; ): Promise<M[]>;
public query<T extends object>(sql: string | { query: string; values: unknown[] }, options: QueryOptionsWithType<QueryTypes.SELECT> & { plain: true }): Promise<T>; public query<T extends object>(sql: string | { query: string; values: unknown[] }, options: QueryOptionsWithType<QueryTypes.SELECT> & { plain: true }): Promise<T>;
public query<T extends object>(sql: string | { query: string; values: unknown[] }, options: QueryOptionsWithType<QueryTypes.SELECT>): Promise<T[]>; public query<T extends object>(sql: string | { query: string; values: unknown[] }, options: QueryOptionsWithType<QueryTypes.SELECT>): Promise<T[]>;
...@@ -1305,7 +1322,7 @@ export class Sequelize extends Hooks { ...@@ -1305,7 +1322,7 @@ export class Sequelize extends Hooks {
* *
* @param [options] The options passed to Model.destroy in addition to truncate * @param [options] The options passed to Model.destroy in addition to truncate
*/ */
public truncate(options?: DestroyOptions): Promise<unknown[]>; public truncate(options?: DestroyOptions<any>): Promise<unknown[]>;
/** /**
* Drop all tables defined through this sequelize instance. This is done by calling Model.drop on each model * Drop all tables defined through this sequelize instance. This is done by calling Model.drop on each model
...@@ -1435,14 +1452,14 @@ export function literal(val: string): Literal; ...@@ -1435,14 +1452,14 @@ export function literal(val: string): Literal;
* *
* @param args Each argument will be joined by AND * @param args Each argument will be joined by AND
*/ */
export function and(...args: (WhereOperators | WhereAttributeHash | Where)[]): AndOperator; export function and(...args: (WhereOperators | WhereAttributeHash<any> | Where)[]): AndOperator<any>;
/** /**
* An OR query * An OR query
* *
* @param args Each argument will be joined by OR * @param args Each argument will be joined by OR
*/ */
export function or(...args: (WhereOperators | WhereAttributeHash | Where)[]): OrOperator; export function or(...args: (WhereOperators | WhereAttributeHash<any> | Where)[]): OrOperator<any>;
/** /**
* Creates an object representing nested where conditions for postgres's json data-type. * Creates an object representing nested where conditions for postgres's json data-type.
...@@ -1455,7 +1472,7 @@ export function or(...args: (WhereOperators | WhereAttributeHash | Where)[]): Or ...@@ -1455,7 +1472,7 @@ export function or(...args: (WhereOperators | WhereAttributeHash | Where)[]): Or
export function json(conditionsOrPath: string | object, value?: string | number | boolean): Json; export function json(conditionsOrPath: string | object, value?: string | number | boolean): Json;
export type AttributeType = Fn | Col | Literal | ModelAttributeColumnOptions | string; export type AttributeType = Fn | Col | Literal | ModelAttributeColumnOptions | string;
export type LogicType = Fn | Col | Literal | OrOperator | AndOperator | WhereOperators | string | symbol | null; export type LogicType = Fn | Col | Literal | OrOperator<any> | AndOperator<any> | WhereOperators | string | symbol | null;
/** /**
* A way of specifying attr = condition. * A way of specifying attr = condition.
......
import { DataType } from './data-types'; import { DataType } from './data-types';
import { Model, WhereOptions } from './model'; import { Model, ModelCtor, WhereOptions } from './model';
export type Primitive = 'string' | 'number' | 'boolean'; export type Primitive = 'string' | 'number' | 'boolean';
...@@ -24,16 +24,21 @@ export function formatNamedParameters(sql: string, parameters: { ...@@ -24,16 +24,21 @@ export function formatNamedParameters(sql: string, parameters: {
}, dialect: string): string; }, dialect: string): string;
export function cloneDeep<T>(obj: T, fn?: (el: unknown) => unknown): T; export function cloneDeep<T>(obj: T, fn?: (el: unknown) => unknown): T;
export interface OptionsForMapping { export interface OptionsForMapping<TAttributes> {
attributes?: string[]; attributes?: string[];
where?: WhereOptions; where?: WhereOptions<TAttributes>;
} }
/** Expand and normalize finder options */ /** Expand and normalize finder options */
export function mapFinderOptions<T extends OptionsForMapping>(options: T, model: typeof Model): T; export function mapFinderOptions<M extends Model, T extends OptionsForMapping<M['_attributes']>>(
options: T,
model: ModelCtor<M>
): T;
/* Used to map field names in attributes and where conditions */ /* Used to map field names in attributes and where conditions */
export function mapOptionFieldNames<T extends OptionsForMapping>(options: T, model: typeof Model): T; export function mapOptionFieldNames<M extends Model, T extends OptionsForMapping<M['_attributes']>>(
options: T, model: ModelCtor<M>
): T;
export function mapWhereFieldNames(attributes: object, model: typeof Model): object; export function mapWhereFieldNames(attributes: object, model: typeof Model): object;
/** Used to map field names in values */ /** Used to map field names in values */
......
import { DataTypes, Model } from 'sequelize'; import { BuildOptions, DataTypes, Model } from 'sequelize';
import { sequelize } from './connection'; import { sequelize } from './connection';
// I really wouldn't recommend this, but if you want you can still use define() and interfaces // I really wouldn't recommend this, but if you want you can still use define() and interfaces
interface User extends Model { interface UserAttributes {
id: number; id: number;
username: string; username: string;
firstName: string; firstName: string;
...@@ -12,19 +12,43 @@ interface User extends Model { ...@@ -12,19 +12,43 @@ interface User extends Model {
updatedAt: Date; updatedAt: Date;
} }
type UserModel = { interface UserCreationAttributes extends Partial<UserAttributes> {}
new (): User
customStaticMethod(): unknown
} & typeof Model;
const User = sequelize.define('User', { firstName: DataTypes.STRING }, { tableName: 'users' }) as UserModel; interface UserModel extends Model<UserAttributes, UserCreationAttributes>, UserAttributes {}
const User = sequelize.define<UserModel>(
'User', { firstName: DataTypes.STRING }, { tableName: 'users' });
async function test() { async function test() {
User.customStaticMethod(); const user: UserModel = new User() as UserModel;
const user2: UserModel | null = await User.findOne();
if (!user2) return;
user2.firstName = 'John';
await user2.save();
}
// The below doesn't define Attribute types, but should still work
interface UntypedUserModel extends Model, UserAttributes {}
type UntypedUserModelStatic = typeof Model & {
new (values?: keyof any, options?: BuildOptions): UntypedUserModel;
customStaticMethod(): unknown;
}
const UntypedUser = sequelize.define<UntypedUserModel>(
'User', { firstName: DataTypes.STRING }, { tableName: 'users' }) as UntypedUserModelStatic;
UntypedUser.customStaticMethod = () => {};
async function testUntyped() {
UntypedUser.customStaticMethod();
const user: User = new User(); const user: UntypedUserModel = new UntypedUser() as UntypedUserModel;
const user2: User = (await User.findOne()) as User; const user2: UntypedUserModel | null = await UntypedUser.findOne();
if (!user2) return;
user2.firstName = 'John'; user2.firstName = 'John';
......
// This file is used as example. // This file is used as example.
import {BuildOptions, DataTypes, Model, Sequelize} from 'sequelize'; import { BuildOptions, DataTypes, Model, Sequelize } from 'sequelize';
import { import {
Association, Association,
HasManyAddAssociationMixin, HasManyAddAssociationMixin,
......
...@@ -5,7 +5,7 @@ import { OptimisticLockError } from '../lib/errors'; ...@@ -5,7 +5,7 @@ import { OptimisticLockError } from '../lib/errors';
async function test() { async function test() {
try { try {
await User.create({ username: 'john_doe' }); await User.create({ username: 'john_doe', firstName: 'John' });
} catch (e) { } catch (e) {
if (e instanceof UniqueConstraintError) { if (e instanceof UniqueConstraintError) {
throw new Error((e as UniqueConstraintError).sql); throw new Error((e as UniqueConstraintError).sql);
......
import { User } from "./models/User";
User.findOne({ where: { firstName: 'John' }});
// The below line should be an error if uncommented, thanks to the new
// TAttributes-based typechecking
// User.findOne({ where: { blah: 'blah2' }});
...@@ -7,11 +7,26 @@ import { ...@@ -7,11 +7,26 @@ import {
FindOptions, FindOptions,
Model, Model,
ModelCtor, ModelCtor,
Op Op,
Optional
} from 'sequelize'; } from 'sequelize';
import { sequelize } from '../connection'; import { sequelize } from '../connection';
export class User extends Model { export interface UserAttributes {
id: number;
username: string;
firstName: string;
lastName: string;
groupId: number;
}
/**
* In this case, we make every single field optional. In real cases, only
* fields that have default/autoincrement values should be made optional.
*/
export interface UserCreationAttributes extends Optional<UserAttributes, 'id' | 'username' | 'lastName' | 'groupId'> {}
export class User extends Model<UserAttributes, UserCreationAttributes> implements UserAttributes {
public static associations: { public static associations: {
group: BelongsTo<User, UserGroup>; group: BelongsTo<User, UserGroup>;
}; };
...@@ -20,11 +35,11 @@ export class User extends Model { ...@@ -20,11 +35,11 @@ export class User extends Model {
public username!: string; public username!: string;
public firstName!: string; public firstName!: string;
public lastName!: string; public lastName!: string;
public groupId!: number;
public createdAt!: Date; public createdAt!: Date;
public updatedAt!: Date; public updatedAt!: Date;
// mixins for association (optional) // mixins for association (optional)
public groupId!: number;
public group?: UserGroup; public group?: UserGroup;
public getGroup!: BelongsToGetAssociationMixin<UserGroup>; public getGroup!: BelongsToGetAssociationMixin<UserGroup>;
public setGroup!: BelongsToSetAssociationMixin<UserGroup, number>; public setGroup!: BelongsToSetAssociationMixin<UserGroup, number>;
...@@ -36,6 +51,7 @@ User.init( ...@@ -36,6 +51,7 @@ User.init(
firstName: DataTypes.STRING, firstName: DataTypes.STRING,
lastName: DataTypes.STRING, lastName: DataTypes.STRING,
username: DataTypes.STRING, username: DataTypes.STRING,
groupId: DataTypes.NUMBER,
}, },
{ {
version: true, version: true,
...@@ -86,7 +102,7 @@ User.afterFind((users, options) => { ...@@ -86,7 +102,7 @@ User.afterFind((users, options) => {
}); });
// TODO: VSCode shows the typing being correctly narrowed but doesn't do it correctly // TODO: VSCode shows the typing being correctly narrowed but doesn't do it correctly
User.addHook('beforeFind', 'test', (options: FindOptions) => { User.addHook('beforeFind', 'test', (options: FindOptions<UserAttributes>) => {
return undefined; return undefined;
}); });
......
...@@ -14,6 +14,8 @@ import { ...@@ -14,6 +14,8 @@ import {
} from 'sequelize'; } from 'sequelize';
import { sequelize } from '../connection'; import { sequelize } from '../connection';
// This class doesn't extend the generic Model<TAttributes>, but should still
// function just fine, with a bit less safe type-checking
export class UserGroup extends Model { export class UserGroup extends Model {
public static associations: { public static associations: {
users: HasMany<UserGroup, User> users: HasMany<UserGroup, User>
......
import { Config, Sequelize, Model, QueryTypes } from 'sequelize'; import { Config, Sequelize, Model, QueryTypes, ModelCtor } from 'sequelize';
import { Fn } from '../lib/utils'; import { Fn } from '../lib/utils';
Sequelize.useCLS({ Sequelize.useCLS({
...@@ -6,7 +6,7 @@ Sequelize.useCLS({ ...@@ -6,7 +6,7 @@ Sequelize.useCLS({
export const sequelize = new Sequelize({ export const sequelize = new Sequelize({
hooks: { hooks: {
afterConnect: (connection, config: Config) => { afterConnect: (connection: unknown, config: Config) => {
// noop // noop
} }
}, },
...@@ -56,7 +56,7 @@ const rnd: Fn = sequelize.random(); ...@@ -56,7 +56,7 @@ const rnd: Fn = sequelize.random();
class Model1 extends Model{} class Model1 extends Model{}
class Model2 extends Model{} class Model2 extends Model{}
const myModel: typeof Model1 = sequelize.models.asd; const myModel: ModelCtor<Model1> = sequelize.models.asd;
myModel.hasOne(Model2) myModel.hasOne(Model2)
myModel.findAll(); myModel.findAll();
......
...@@ -8,7 +8,7 @@ async function trans() { ...@@ -8,7 +8,7 @@ async function trans() {
transaction.afterCommit(() => console.log('transaction complete')); transaction.afterCommit(() => console.log('transaction complete'));
User.create( User.create(
{ {
data: 123, firstName: 'John',
}, },
{ {
transaction, transaction,
......
...@@ -39,10 +39,16 @@ where = whereWithOptionals; ...@@ -39,10 +39,16 @@ where = whereWithOptionals;
const and: AndOperator = { const and: AndOperator = {
[Op.and]: { a: 5 }, // AND (a = 5) [Op.and]: { a: 5 }, // AND (a = 5)
}; };
const typedAnd: AndOperator<{ a: number }> = {
[Op.and]: { a: 5 }, // AND (a = 5)
};
const or: OrOperator = { const or: OrOperator = {
[Op.or]: [{ a: 5 }, { a: 6 }], // (a = 5 OR a = 6) [Op.or]: [{ a: 5 }, { a: 6 }], // (a = 5 OR a = 6)
}; };
const typedOr: OrOperator<{ a: number }> = {
[Op.or]: [{ a: 5 }, { a: 6 }], // (a = 5 OR a = 6)
};
let operators: WhereOperators = { let operators: WhereOperators = {
[Op.gt]: 6, // > 6 [Op.gt]: 6, // > 6
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!