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

Commit 0b868c83 by Rémy Dufour Committed by Sushant

feat(types): add generics types for associations (#10524)

1 parent 35780624
import { ColumnOptions, Model } from '../model';
import { ColumnOptions, Model, ModelCtor } from '../model';
export abstract class Association {
export abstract class Association<S extends Model = Model, T extends Model = Model> {
public associationType: string;
public source: typeof Model;
public target: typeof Model;
public source: ModelCtor<S>;
public target: ModelCtor<T>;
public isSelfAssociation: boolean;
public isSingleAssociation: boolean;
public isMultiAssociation: boolean;
......
......@@ -6,6 +6,7 @@ import {
InstanceDestroyOptions,
InstanceUpdateOptions,
Model,
ModelCtor,
Transactionable,
WhereOptions,
} from '../model';
......@@ -68,10 +69,10 @@ export interface BelongsToManyOptions extends ManyToManyOptions {
timestamps?: boolean;
}
export class BelongsToMany extends Association {
export class BelongsToMany<S extends Model = Model, T extends Model = Model> extends Association<S, T> {
public otherKey: string;
public accessors: MultiAssociationAccessors;
constructor(source: typeof Model, target: typeof Model, options: BelongsToManyOptions);
constructor(source: ModelCtor<S>, target: ModelCtor<T>, options: BelongsToManyOptions);
}
/**
......
import { DataType } from '../data-types';
import { CreateOptions, FindOptions, Model, SaveOptions } from '../model';
import { CreateOptions, FindOptions, Model, ModelCtor, SaveOptions } from '../model';
import { Promise } from '../promise';
import { Association, AssociationOptions, SingleAssociationAccessors } from './base';
// type ModelCtor<M extends Model> = InstanceType<typeof M>;
/**
* Options provided when associating models with belongsTo relationship
*
......@@ -21,9 +22,9 @@ export interface BelongsToOptions extends AssociationOptions {
keyType?: DataType;
}
export class BelongsTo extends Association {
export class BelongsTo<S extends Model = Model, T extends Model = Model> extends Association<S, T> {
public accessors: SingleAssociationAccessors;
constructor(source: typeof Model, target: typeof Model, options: BelongsToOptions);
constructor(source: ModelCtor<S>, target: ModelCtor<T>, options: BelongsToOptions);
}
/**
......
......@@ -5,6 +5,7 @@ import {
FindOptions,
InstanceUpdateOptions,
Model,
ModelCtor,
Transactionable,
WhereOptions,
} from '../model';
......@@ -22,9 +23,9 @@ export interface HasManyOptions extends ManyToManyOptions {
keyType?: DataType;
}
export class HasMany extends Association {
export class HasMany<S extends Model = Model, T extends Model = Model> extends Association<S, T> {
public accessors: MultiAssociationAccessors;
constructor(source: typeof Model, target: typeof Model, options: HasManyOptions);
constructor(source: ModelCtor<S>, target: ModelCtor<T>, options: HasManyOptions);
}
/**
......
import { DataType } from '../data-types';
import { CreateOptions, FindOptions, Model, SaveOptions } from '../model';
import { CreateOptions, FindOptions, Model, ModelCtor, SaveOptions } from '../model';
import { Promise } from '../promise';
import { Association, AssociationOptions, SingleAssociationAccessors } from './base';
......@@ -13,9 +13,9 @@ export interface HasOneOptions extends AssociationOptions {
keyType?: DataType;
}
export class HasOne extends Association {
export class HasOne<S extends Model = Model, T extends Model = Model> extends Association<S, T> {
public accessors: SingleAssociationAccessors;
constructor(source: typeof Model, target: typeof Model, options: HasOneOptions);
constructor(source: ModelCtor<S>, target: ModelCtor<T>, options: HasOneOptions);
}
/**
......
......@@ -2192,7 +2192,9 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param target The model that will be associated with hasOne relationship
* @param options Options for the association
*/
public static hasOne(target: typeof Model, options?: HasOneOptions): HasOne;
public static hasOne<M extends Model, T extends Model>(
this: ModelCtor<M>, target: ModelCtor<T>, options?: HasOneOptions
): HasOne<M, T>;
/**
* Creates an association between this (the source) and the provided target. The foreign key is added on the
......@@ -2203,8 +2205,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param target The model that will be associated with hasOne relationship
* @param options Options for the association
*/
public static belongsTo(target: typeof Model, options?: BelongsToOptions): BelongsTo;
public static belongsTo<M extends Model, T extends Model>(
this: ModelCtor<M>, target: ModelCtor<T>, options?: BelongsToOptions
): BelongsTo<M, T>;
/**
* Create an association that is either 1:m or n:m.
*
......@@ -2257,7 +2261,9 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param target The model that will be associated with hasOne relationship
* @param options Options for the association
*/
public static hasMany(target: typeof Model, options?: HasManyOptions): HasMany;
public static hasMany<M extends Model, T extends Model>(
this: ModelCtor<M>, target: ModelCtor<T>, options?: HasManyOptions
): HasMany<M, T>;
/**
* Create an N:M association with a join table
......@@ -2307,7 +2313,9 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* @param options Options for the association
*
*/
public static belongsToMany(target: typeof Model, options: BelongsToManyOptions): BelongsToMany;
public static belongsToMany<M extends Model, T extends Model>(
this: ModelCtor<M>, target: ModelCtor<T>, options: BelongsToManyOptions
): BelongsToMany<M, T>;
/**
* Returns true if this instance has not yet been persisted to the database
......@@ -2511,4 +2519,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
public toJSON(): object;
}
export type ModelType = typeof Model;
export type ModelCtor<M extends Model> = { new (): M } & ModelType;
export default Model;
......@@ -6,12 +6,13 @@ import {
DataTypes,
FindOptions,
Model,
ModelCtor
} from 'sequelize';
import { sequelize } from '../connection';
export class User extends Model {
public static associations: {
group: BelongsTo
group: BelongsTo<User, UserGroup>;
};
public id: number;
......@@ -68,7 +69,12 @@ User.afterFind((users, options) => {
User.addHook('beforeFind', 'test', (options: FindOptions) => {
return undefined;
});
// associate
// it is important to import _after_ the model above is already exported so the circular reference works.
import { UserGroup } from './UserGroup';
export const Group = User.belongsTo(UserGroup, { as: 'group', foreignKey: 'groupId' });
// associations refer to their Model
const userType: ModelCtor<User> = User.associations.group.source;
const groupType: ModelCtor<UserGroup> = User.associations.group.target;
......@@ -16,7 +16,7 @@ import { sequelize } from '../connection';
export class UserGroup extends Model {
public static associations: {
users: HasMany
users: HasMany<UserGroup, User>
};
public id: number;
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!