From 6be322fcd23a49f232f5fc44b6dc30b3c2bae7f8 Mon Sep 17 00:00:00 2001 From: Dominic Watson Date: Sun, 13 Dec 2020 23:45:26 +0000 Subject: [PATCH 1/6] Fix typeof Model errors throughout by using typeof Model generics --- .../belongs-to-many-association.ts | 11 ++++++----- .../belongs-to-many/belongs-to-many-options.ts | 4 ++-- .../belongs-to-many/belongs-to-many.ts | 16 ++++++++-------- .../belongs-to/belongs-to-association.ts | 8 ++++---- src/associations/belongs-to/belongs-to.ts | 6 +++--- src/associations/foreign-key/foreign-key-meta.ts | 4 ++-- .../foreign-key/foreign-key-service.ts | 13 +++++++------ src/associations/foreign-key/foreign-key.ts | 2 +- src/associations/has/has-association.ts | 9 +++++---- src/associations/has/has-many.ts | 6 +++--- src/associations/has/has-one.ts | 6 +++--- src/associations/shared/association-service.ts | 14 +++++++------- src/associations/shared/base-association.ts | 10 +++++----- src/associations/through/through-options.ts | 4 ++-- src/model/model/model.ts | 4 ++-- src/model/shared/model-class-getter.ts | 4 ++-- src/scopes/default-scope.ts | 4 ++-- src/scopes/scope-find-options.ts | 10 +++++----- src/scopes/scope-options.ts | 4 ++-- src/scopes/scope-service.ts | 8 ++++---- src/scopes/scope-table-options.ts | 4 ++-- src/scopes/scopes.ts | 4 ++-- src/sequelize/sequelize/sequelize.ts | 4 ++-- 23 files changed, 81 insertions(+), 78 deletions(-) diff --git a/src/associations/belongs-to-many/belongs-to-many-association.ts b/src/associations/belongs-to-many/belongs-to-many-association.ts index 8924c367..9045092b 100644 --- a/src/associations/belongs-to-many/belongs-to-many-association.ts +++ b/src/associations/belongs-to-many/belongs-to-many-association.ts @@ -1,4 +1,4 @@ -import {BelongsToManyOptions as OriginBelongsToManyOptions, Model, ThroughOptions} from "sequelize"; +import {BelongsToManyOptions as OriginBelongsToManyOptions, ThroughOptions} from "sequelize"; import {BaseAssociation} from '../shared/base-association'; import {BelongsToManyOptions} from './belongs-to-many-options'; @@ -8,11 +8,12 @@ import {ModelClassGetter} from "../../model/shared/model-class-getter"; import {Association} from "../shared/association"; import {Sequelize} from "../../sequelize/sequelize/sequelize"; import {UnionAssociationOptions} from "../shared/union-association-options"; +import {ModelType} from "../../model/model/model"; -export class BelongsToManyAssociation extends BaseAssociation { +export class BelongsToManyAssociation extends BaseAssociation { - constructor(associatedClassGetter: ModelClassGetter, - protected options: BelongsToManyOptions) { + constructor(associatedClassGetter: ModelClassGetter, + protected options: BelongsToManyOptions) { super(associatedClassGetter, options); } @@ -20,7 +21,7 @@ export class BelongsToManyAssociation extends BaseAssociation { return Association.BelongsToMany; } - getSequelizeOptions(model: typeof Model, + getSequelizeOptions(model: ModelType, sequelize: Sequelize): UnionAssociationOptions { const options: OriginBelongsToManyOptions = {...this.options as any}; const associatedClass = this.getAssociatedClass(); diff --git a/src/associations/belongs-to-many/belongs-to-many-options.ts b/src/associations/belongs-to-many/belongs-to-many-options.ts index 248e4930..895b1300 100644 --- a/src/associations/belongs-to-many/belongs-to-many-options.ts +++ b/src/associations/belongs-to-many/belongs-to-many-options.ts @@ -3,8 +3,8 @@ import {ModelClassGetter} from "../../model/shared/model-class-getter"; import {ThroughOptions} from "../through/through-options"; -export type BelongsToManyOptions = { +export type BelongsToManyOptions = { [K in keyof OriginBelongsToManyOptions]: K extends 'through' - ? ModelClassGetter | string | ThroughOptions + ? ModelClassGetter | string | ThroughOptions : OriginBelongsToManyOptions[K] }; diff --git a/src/associations/belongs-to-many/belongs-to-many.ts b/src/associations/belongs-to-many/belongs-to-many.ts index 0323cf33..2d80135a 100644 --- a/src/associations/belongs-to-many/belongs-to-many.ts +++ b/src/associations/belongs-to-many/belongs-to-many.ts @@ -3,19 +3,19 @@ import {BelongsToManyAssociation} from './belongs-to-many-association'; import {ModelClassGetter} from "../../model/shared/model-class-getter"; import {addAssociation} from "../shared/association-service"; -export function BelongsToMany(associatedClassGetter: ModelClassGetter, - through: ModelClassGetter | string, +export function BelongsToMany(associatedClassGetter: ModelClassGetter, + through: ModelClassGetter | string, foreignKey?: string, otherKey?: string): Function; -export function BelongsToMany(associatedClassGetter: ModelClassGetter, - options: BelongsToManyOptions): Function; -export function BelongsToMany(associatedClassGetter: ModelClassGetter, - throughOrOptions: ModelClassGetter | string | BelongsToManyOptions, +export function BelongsToMany(associatedClassGetter: ModelClassGetter, + options: BelongsToManyOptions): Function; +export function BelongsToMany(associatedClassGetter: ModelClassGetter, + throughOrOptions: ModelClassGetter | string | BelongsToManyOptions, foreignKey?: string, otherKey?: string): Function { return (target: any, propertyName: string) => { - let options: Partial = {foreignKey, otherKey}; + let options: Partial> = {foreignKey, otherKey}; if (typeof throughOrOptions === 'string' || typeof throughOrOptions === 'function') { @@ -28,7 +28,7 @@ export function BelongsToMany(associatedClassGetter: ModelClassGetter, addAssociation(target, new BelongsToManyAssociation( associatedClassGetter, - options as BelongsToManyOptions, + options as BelongsToManyOptions, ) ); }; diff --git a/src/associations/belongs-to/belongs-to-association.ts b/src/associations/belongs-to/belongs-to-association.ts index 73212441..b26035e1 100644 --- a/src/associations/belongs-to/belongs-to-association.ts +++ b/src/associations/belongs-to/belongs-to-association.ts @@ -4,12 +4,12 @@ import {BaseAssociation} from '../shared/base-association'; import {getForeignKeyOptions} from "../foreign-key/foreign-key-service"; import {ModelClassGetter} from "../../model/shared/model-class-getter"; import {Association} from "../shared/association"; -import {Model} from "../../model/model/model"; +import {ModelType} from "../../model/model/model"; import {UnionAssociationOptions} from "../shared/union-association-options"; -export class BelongsToAssociation extends BaseAssociation { +export class BelongsToAssociation extends BaseAssociation { - constructor(associatedClassGetter: ModelClassGetter, + constructor(associatedClassGetter: ModelClassGetter, protected options: BelongsToOptions) { super(associatedClassGetter, options); } @@ -18,7 +18,7 @@ export class BelongsToAssociation extends BaseAssociation { return Association.BelongsTo; } - getSequelizeOptions(model: typeof Model): UnionAssociationOptions { + getSequelizeOptions(model: ModelType): UnionAssociationOptions { const associatedClass = this.getAssociatedClass(); const foreignKey = getForeignKeyOptions(associatedClass, model, this.options.foreignKey); diff --git a/src/associations/belongs-to/belongs-to.ts b/src/associations/belongs-to/belongs-to.ts index a09a391a..5ac50971 100644 --- a/src/associations/belongs-to/belongs-to.ts +++ b/src/associations/belongs-to/belongs-to.ts @@ -4,11 +4,11 @@ import {BelongsToAssociation} from './belongs-to-association'; import {ModelClassGetter} from "../../model/shared/model-class-getter"; import {addAssociation, getPreparedAssociationOptions} from "../shared/association-service"; -export function BelongsTo(associatedClassGetter: ModelClassGetter, foreignKey?: string): Function; +export function BelongsTo(associatedClassGetter: ModelClassGetter, foreignKey?: string): Function; -export function BelongsTo(associatedClassGetter: ModelClassGetter, options?: BelongsToOptions): Function; +export function BelongsTo(associatedClassGetter: ModelClassGetter, options?: BelongsToOptions): Function; -export function BelongsTo(associatedClassGetter: ModelClassGetter, optionsOrForeignKey?: string | BelongsToOptions): Function { +export function BelongsTo(associatedClassGetter: ModelClassGetter, optionsOrForeignKey?: string | BelongsToOptions): Function { return (target: any, propertyName: string) => { const options: BelongsToOptions = getPreparedAssociationOptions(optionsOrForeignKey); diff --git a/src/associations/foreign-key/foreign-key-meta.ts b/src/associations/foreign-key/foreign-key-meta.ts index 768ce922..5ed86fd2 100644 --- a/src/associations/foreign-key/foreign-key-meta.ts +++ b/src/associations/foreign-key/foreign-key-meta.ts @@ -1,7 +1,7 @@ import {ModelClassGetter} from "../../model/shared/model-class-getter"; -export interface ForeignKeyMeta { +export interface ForeignKeyMeta { - relatedClassGetter: ModelClassGetter; + relatedClassGetter: ModelClassGetter; foreignKey: string; } diff --git a/src/associations/foreign-key/foreign-key-service.ts b/src/associations/foreign-key/foreign-key-service.ts index aeccf881..6de931e5 100644 --- a/src/associations/foreign-key/foreign-key-service.ts +++ b/src/associations/foreign-key/foreign-key-service.ts @@ -1,12 +1,13 @@ -import {ForeignKeyOptions, Model} from "sequelize"; +import {ForeignKeyOptions} from "sequelize"; import {ForeignKeyMeta} from './foreign-key-meta'; import {ModelClassGetter} from "../../model/shared/model-class-getter"; +import {ModelType} from "../../model/model/model"; const FOREIGN_KEYS_KEY = 'sequelize:foreignKeys'; -export function getForeignKeyOptions(relatedClass: typeof Model, - classWithForeignKey?: typeof Model, +export function getForeignKeyOptions(relatedClass: ModelType, + classWithForeignKey?: ModelType, foreignKey?: string | ForeignKeyOptions): ForeignKeyOptions { let foreignKeyOptions: ForeignKeyOptions = {}; @@ -36,8 +37,8 @@ export function getForeignKeyOptions(relatedClass: typeof Model, /** * Adds foreign key meta data for specified class */ -export function addForeignKey(target: any, - relatedClassGetter: ModelClassGetter, +export function addForeignKey(target: any, + relatedClassGetter: ModelClassGetter, foreignKey: string): void { let foreignKeys = getForeignKeys(target); if (!foreignKeys) { @@ -53,7 +54,7 @@ export function addForeignKey(target: any, /** * Returns foreign key meta data from specified class */ -export function getForeignKeys(target: any): ForeignKeyMeta[] | undefined { +export function getForeignKeys(target: any): ForeignKeyMeta[] | undefined { const foreignKeys = Reflect.getMetadata(FOREIGN_KEYS_KEY, target); if (foreignKeys) { return [...foreignKeys]; diff --git a/src/associations/foreign-key/foreign-key.ts b/src/associations/foreign-key/foreign-key.ts index f7f00057..789040bc 100644 --- a/src/associations/foreign-key/foreign-key.ts +++ b/src/associations/foreign-key/foreign-key.ts @@ -1,7 +1,7 @@ import {addForeignKey} from "./foreign-key-service"; import {ModelClassGetter} from "../../model/shared/model-class-getter"; -export function ForeignKey(relatedClassGetter: ModelClassGetter): Function { +export function ForeignKey(relatedClassGetter: ModelClassGetter): Function { return (target: any, propertyName: string) => { addForeignKey(target, relatedClassGetter, propertyName); }; diff --git a/src/associations/has/has-association.ts b/src/associations/has/has-association.ts index 4a3379c3..b8145e76 100644 --- a/src/associations/has/has-association.ts +++ b/src/associations/has/has-association.ts @@ -1,14 +1,15 @@ -import {HasManyOptions, HasOneOptions, Model} from 'sequelize'; +import {HasManyOptions, HasOneOptions} from 'sequelize'; import {BaseAssociation} from '../shared/base-association'; import {getForeignKeyOptions} from "../foreign-key/foreign-key-service"; import {ModelClassGetter} from "../../model/shared/model-class-getter"; import {Association} from "../shared/association"; import {UnionAssociationOptions} from "../shared/union-association-options"; +import {ModelType} from '../../model/model/model'; -export class HasAssociation extends BaseAssociation { +export class HasAssociation extends BaseAssociation { - constructor(associatedClassGetter: ModelClassGetter, + constructor(associatedClassGetter: ModelClassGetter, protected options: HasManyOptions | HasOneOptions, private association: Association) { super(associatedClassGetter, options); @@ -18,7 +19,7 @@ export class HasAssociation extends BaseAssociation { return this.association; } - getSequelizeOptions(model: typeof Model): UnionAssociationOptions { + getSequelizeOptions(model: ModelType): UnionAssociationOptions { const options = {...this.options}; const associatedClass = this.getAssociatedClass(); diff --git a/src/associations/has/has-many.ts b/src/associations/has/has-many.ts index 53f6d1e2..fc8c218f 100644 --- a/src/associations/has/has-many.ts +++ b/src/associations/has/has-many.ts @@ -5,11 +5,11 @@ import {ModelClassGetter} from "../../model/shared/model-class-getter"; import {addAssociation, getPreparedAssociationOptions} from "../shared/association-service"; import {Association} from "../shared/association"; -export function HasMany(associatedClassGetter: ModelClassGetter, foreignKey?: string): Function; +export function HasMany(associatedClassGetter: ModelClassGetter, foreignKey?: string): Function; -export function HasMany(associatedClassGetter: ModelClassGetter, options?: HasManyOptions): Function; +export function HasMany(associatedClassGetter: ModelClassGetter, options?: HasManyOptions): Function; -export function HasMany(associatedClassGetter: ModelClassGetter, optionsOrForeignKey?: string | HasManyOptions): Function { +export function HasMany(associatedClassGetter: ModelClassGetter, optionsOrForeignKey?: string | HasManyOptions): Function { return (target: any, propertyName: string) => { const options: HasManyOptions = getPreparedAssociationOptions(optionsOrForeignKey); diff --git a/src/associations/has/has-one.ts b/src/associations/has/has-one.ts index c25f0b8f..e45fa0e5 100644 --- a/src/associations/has/has-one.ts +++ b/src/associations/has/has-one.ts @@ -5,11 +5,11 @@ import {ModelClassGetter} from "../../model/shared/model-class-getter"; import {addAssociation, getPreparedAssociationOptions} from "../shared/association-service"; import {Association} from "../shared/association"; -export function HasOne(associatedClassGetter: ModelClassGetter, foreignKey?: string): Function; +export function HasOne(associatedClassGetter: ModelClassGetter, foreignKey?: string): Function; -export function HasOne(associatedClassGetter: ModelClassGetter, options?: HasOneOptions): Function; +export function HasOne(associatedClassGetter: ModelClassGetter, options?: HasOneOptions): Function; -export function HasOne(associatedClassGetter: ModelClassGetter, optionsOrForeignKey?: string | HasOneOptions): Function { +export function HasOne(associatedClassGetter: ModelClassGetter, optionsOrForeignKey?: string | HasOneOptions): Function { return (target: any, propertyName: string) => { const options: HasOneOptions = getPreparedAssociationOptions(optionsOrForeignKey); diff --git a/src/associations/shared/association-service.ts b/src/associations/shared/association-service.ts index 361124e9..f796d879 100644 --- a/src/associations/shared/association-service.ts +++ b/src/associations/shared/association-service.ts @@ -27,8 +27,8 @@ export function getPreparedAssociationOptions(optionsOrForeignKey?: string | Non /** * Stores association meta data for specified class */ -export function addAssociation(target: any, - association: BaseAssociation) { +export function addAssociation(target: any, + association: BaseAssociation) { let associations = getAssociations(target); @@ -42,20 +42,20 @@ export function addAssociation(target: any, /** * Returns association meta data from specified class */ -export function getAssociations(target: any): BaseAssociation[] | undefined { +export function getAssociations(target: any): BaseAssociation[] | undefined { const associations = Reflect.getMetadata(ASSOCIATIONS_KEY, target); if (associations) { return [...associations]; } } -export function setAssociations(target: any, associations: BaseAssociation[]) { +export function setAssociations(target: any, associations: BaseAssociation[]) { Reflect.defineMetadata(ASSOCIATIONS_KEY, associations, target); } -export function getAssociationsByRelation(target: any, - relatedClass: any): BaseAssociation[] { - const associations = getAssociations(target); +export function getAssociationsByRelation(target: any, + relatedClass: any): BaseAssociation[] { + const associations = getAssociations(target); return (associations || []).filter(association => { const _relatedClass = association.getAssociatedClass(); return ( diff --git a/src/associations/shared/base-association.ts b/src/associations/shared/base-association.ts index 1f6143fe..ae902dcd 100644 --- a/src/associations/shared/base-association.ts +++ b/src/associations/shared/base-association.ts @@ -1,20 +1,20 @@ import {UnionAssociationOptions} from './union-association-options'; import {Association} from './association'; import {ModelClassGetter} from "../../model/shared/model-class-getter"; -import {Model} from "../../model/model/model"; +import {ModelType} from "../../model/model/model"; import {Sequelize} from "../../sequelize/sequelize/sequelize"; -export abstract class BaseAssociation { +export abstract class BaseAssociation { - constructor(private associatedClassGetter: ModelClassGetter, + constructor(private associatedClassGetter: ModelClassGetter, protected options: UnionAssociationOptions) { } abstract getAssociation(): Association; - abstract getSequelizeOptions(model: typeof Model, + abstract getSequelizeOptions(model: ModelType, sequelize: Sequelize): UnionAssociationOptions; - getAssociatedClass(): typeof Model { + getAssociatedClass(): ModelType { return this.associatedClassGetter(); } diff --git a/src/associations/through/through-options.ts b/src/associations/through/through-options.ts index 6e1c2075..bf572385 100644 --- a/src/associations/through/through-options.ts +++ b/src/associations/through/through-options.ts @@ -1,8 +1,8 @@ import {ThroughOptions as OriginThroughOptions} from 'sequelize'; import {ModelClassGetter} from "../../model/shared/model-class-getter"; -export type ThroughOptions = { +export type ThroughOptions = { [K in keyof OriginThroughOptions]: K extends 'model' - ? ModelClassGetter | string + ? ModelClassGetter | string : OriginThroughOptions[K] }; diff --git a/src/model/model/model.ts b/src/model/model/model.ts index 92bd8086..f4bb38b5 100644 --- a/src/model/model/model.ts +++ b/src/model/model/model.ts @@ -8,8 +8,8 @@ import {AssociationCountOptions} from "./association/association-count-options"; import {AssociationActionOptions} from "./association/association-action-options"; import {AssociationCreateOptions} from "./association/association-create-options"; -export type ModelType = typeof Model; -export type ModelCtor = (new () => M) & ModelType; +export type ModelType = new (values?: TCreationAttributes, options?: any) => Model; +export type ModelCtor = (new () => M) & typeof Model; export type $GetType = NonNullable extends any[] ? NonNullable : (NonNullable | null); diff --git a/src/model/shared/model-class-getter.ts b/src/model/shared/model-class-getter.ts index 29200d8b..84ef5148 100644 --- a/src/model/shared/model-class-getter.ts +++ b/src/model/shared/model-class-getter.ts @@ -1,3 +1,3 @@ -import {Model} from "../model/model"; +import {ModelType} from "../model/model"; -export type ModelClassGetter = (returns?: void) => typeof Model; +export type ModelClassGetter = (returns?: void) => ModelType; diff --git a/src/scopes/default-scope.ts b/src/scopes/default-scope.ts index 19186570..5f498d3c 100644 --- a/src/scopes/default-scope.ts +++ b/src/scopes/default-scope.ts @@ -11,12 +11,12 @@ export function DefaultScope(scopeGetter: DefaultScopeGetter): Function; * Decorator for defining default Model scope * @deprecated */ -export function DefaultScope(scope: ScopeFindOptions): Function; +export function DefaultScope(scope: ScopeFindOptions): Function; /** * Decorator for defining default Model scope */ -export function DefaultScope(scopeOrSsopeGetter: ScopeFindOptions | DefaultScopeGetter): Function { +export function DefaultScope(scopeOrSsopeGetter: ScopeFindOptions | DefaultScopeGetter): Function { return (target: any) => { if (typeof scopeOrSsopeGetter === 'function') { addScopeOptionsGetter(target.prototype, {getDefaultScope: scopeOrSsopeGetter}); diff --git a/src/scopes/scope-find-options.ts b/src/scopes/scope-find-options.ts index 4902a9d0..f23dc624 100644 --- a/src/scopes/scope-find-options.ts +++ b/src/scopes/scope-find-options.ts @@ -1,16 +1,16 @@ import {Association, FindOptions, IncludeOptions} from "sequelize"; import {ModelClassGetter} from "../model/shared/model-class-getter"; -export type ScopeIncludeOptions = { +export type ScopeIncludeOptions = { [K in keyof IncludeOptions]: K extends 'model' - ? ModelClassGetter + ? ModelClassGetter : (K extends 'include' - ? ScopeIncludeOptions + ? ScopeIncludeOptions : IncludeOptions[K]) }; -export type ScopeFindOptions = { +export type ScopeFindOptions = { [K in keyof FindOptions]: K extends 'include' - ? ModelClassGetter[] | Association[] | ScopeIncludeOptions[] | { all: true } + ? ModelClassGetter[] | Association[] | ScopeIncludeOptions[] | { all: true } : FindOptions[K] }; diff --git a/src/scopes/scope-options.ts b/src/scopes/scope-options.ts index 962cdee4..5fef3700 100644 --- a/src/scopes/scope-options.ts +++ b/src/scopes/scope-options.ts @@ -2,8 +2,8 @@ import {ScopeTableOptions} from './scope-table-options'; import {ScopeFindOptions} from "./scope-find-options"; import {FindOptions} from "sequelize"; -export interface ScopeOptions extends ScopeTableOptions { - defaultScope?: ScopeFindOptions; +export interface ScopeOptions extends ScopeTableOptions { + defaultScope?: ScopeFindOptions; } export interface ScopeOptionsGetters { diff --git a/src/scopes/scope-service.ts b/src/scopes/scope-service.ts index 81fb6bd8..8b0e6b83 100644 --- a/src/scopes/scope-service.ts +++ b/src/scopes/scope-service.ts @@ -70,7 +70,7 @@ export const resolvesDeprecatedScopes = (model: ModelCtor) => { * Adds scope option meta data for specified prototype * @deprecated */ -export function addScopeOptions(target: any, options: ScopeOptions): void { +export function addScopeOptions(target: any, options: ScopeOptions): void { const _options = getScopeOptions(target) || {}; setScopeOptions(target, deepAssign({}, _options, options)); } @@ -79,7 +79,7 @@ export function addScopeOptions(target: any, options: ScopeOptions): void { * Returns scope option meta data from specified target * @deprecated */ -export function getScopeOptions(target: any): ScopeOptions | undefined { +export function getScopeOptions(target: any): ScopeOptions | undefined { const options = Reflect.getMetadata(SCOPES_KEY, target); if (options) { return deepAssign({}, options); @@ -89,7 +89,7 @@ export function getScopeOptions(target: any): ScopeOptions | undefined { /** * @deprecated */ -function resolveDeprecatedScope(scopeName: string, model: ModelCtor, options: ScopeFindOptions | Function | undefined): void { +function resolveDeprecatedScope(scopeName: string, model: ModelCtor, options: ScopeFindOptions | Function | undefined): void { if (typeof options === 'function') { const fn: Function = options; options = (...args: any[]) => inferAlias(fn(...args), model); @@ -103,6 +103,6 @@ function resolveDeprecatedScope(scopeName: string, model: ModelCtor, options: Sc * Set scope option meta data for specified prototype * @deprecated */ -function setScopeOptions(target: any, options: ScopeOptions): void { +function setScopeOptions(target: any, options: ScopeOptions): void { Reflect.defineMetadata(SCOPES_KEY, options, target); } diff --git a/src/scopes/scope-table-options.ts b/src/scopes/scope-table-options.ts index 052a220b..54b0dff2 100644 --- a/src/scopes/scope-table-options.ts +++ b/src/scopes/scope-table-options.ts @@ -1,5 +1,5 @@ import {ScopeFindOptions} from "./scope-find-options"; -export interface ScopeTableOptions { - [scopeName: string]: ScopeFindOptions | Function | undefined; +export interface ScopeTableOptions { + [scopeName: string]: ScopeFindOptions | Function | undefined; } diff --git a/src/scopes/scopes.ts b/src/scopes/scopes.ts index 6cff170b..3ad04d41 100644 --- a/src/scopes/scopes.ts +++ b/src/scopes/scopes.ts @@ -11,12 +11,12 @@ export function Scopes(scopesGetter: ScopesOptionsGetter): Function; * Decorator for defining Model scopes * @deprecated */ -export function Scopes(scopes: ScopeTableOptions): Function; +export function Scopes(scopes: ScopeTableOptions): Function; /** * Decorator for defining Model scopes */ -export function Scopes(scopesOrScopesGetter: ScopeTableOptions | ScopesOptionsGetter): Function { +export function Scopes(scopesOrScopesGetter: ScopeTableOptions | ScopesOptionsGetter): Function { return (target: any) => { if (typeof scopesOrScopesGetter === 'function') { addScopeOptionsGetter(target.prototype, { diff --git a/src/sequelize/sequelize/sequelize.ts b/src/sequelize/sequelize/sequelize.ts index b13ec6af..79c069b0 100644 --- a/src/sequelize/sequelize/sequelize.ts +++ b/src/sequelize/sequelize/sequelize.ts @@ -2,7 +2,7 @@ import {InitOptions, Sequelize as OriginSequelize} from 'sequelize'; import {ModelNotInitializedError} from "../../model/shared/model-not-initialized-error"; import {ModelMatch, SequelizeOptions} from "./sequelize-options"; import {getModels, prepareArgs} from "./sequelize-service"; -import {Model, ModelCtor} from "../../model/model/model"; +import {Model, ModelCtor, ModelType} from "../../model/model/model"; import {getModelName, getOptions} from "../../model/shared/model-service"; import {resolveScopes} from "../../scopes/scope-service"; import {installHooks} from "../../hooks/shared/hooks-service"; @@ -33,7 +33,7 @@ export class Sequelize extends OriginSequelize { } } - model(model: string | typeof Model): ModelCtor { + model(model: string | ModelType): ModelCtor { if (typeof model !== 'string') { return super.model(getModelName(model.prototype)) as ModelCtor; } From b1a5135ab5b267a12664dcef6c9f376e6190a9cc Mon Sep 17 00:00:00 2001 From: KapitanOczywisty <44417092+KapitanOczywisty@users.noreply.github.com> Date: Sat, 6 Feb 2021 12:04:17 +0100 Subject: [PATCH 2/6] Fix lint errors --- .../belongs-to-many/belongs-to-many.ts | 14 +++++++------- .../foreign-key/foreign-key-service.ts | 8 ++++---- src/associations/shared/association-service.ts | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/associations/belongs-to-many/belongs-to-many.ts b/src/associations/belongs-to-many/belongs-to-many.ts index 2d80135a..59e0285c 100644 --- a/src/associations/belongs-to-many/belongs-to-many.ts +++ b/src/associations/belongs-to-many/belongs-to-many.ts @@ -4,15 +4,15 @@ import {ModelClassGetter} from "../../model/shared/model-class-getter"; import {addAssociation} from "../shared/association-service"; export function BelongsToMany(associatedClassGetter: ModelClassGetter, - through: ModelClassGetter | string, - foreignKey?: string, - otherKey?: string): Function; + through: ModelClassGetter | string, + foreignKey?: string, + otherKey?: string): Function; export function BelongsToMany(associatedClassGetter: ModelClassGetter, - options: BelongsToManyOptions): Function; + options: BelongsToManyOptions): Function; export function BelongsToMany(associatedClassGetter: ModelClassGetter, - throughOrOptions: ModelClassGetter | string | BelongsToManyOptions, - foreignKey?: string, - otherKey?: string): Function { + throughOrOptions: ModelClassGetter | string | BelongsToManyOptions, + foreignKey?: string, + otherKey?: string): Function { return (target: any, propertyName: string) => { let options: Partial> = {foreignKey, otherKey}; diff --git a/src/associations/foreign-key/foreign-key-service.ts b/src/associations/foreign-key/foreign-key-service.ts index 6de931e5..e4ee7b93 100644 --- a/src/associations/foreign-key/foreign-key-service.ts +++ b/src/associations/foreign-key/foreign-key-service.ts @@ -7,8 +7,8 @@ import {ModelType} from "../../model/model/model"; const FOREIGN_KEYS_KEY = 'sequelize:foreignKeys'; export function getForeignKeyOptions(relatedClass: ModelType, - classWithForeignKey?: ModelType, - foreignKey?: string | ForeignKeyOptions): ForeignKeyOptions { + classWithForeignKey?: ModelType, + foreignKey?: string | ForeignKeyOptions): ForeignKeyOptions { let foreignKeyOptions: ForeignKeyOptions = {}; if (typeof foreignKey === 'string') { @@ -38,8 +38,8 @@ export function getForeignKeyOptions(rela * Adds foreign key meta data for specified class */ export function addForeignKey(target: any, - relatedClassGetter: ModelClassGetter, - foreignKey: string): void { + relatedClassGetter: ModelClassGetter, + foreignKey: string): void { let foreignKeys = getForeignKeys(target); if (!foreignKeys) { foreignKeys = []; diff --git a/src/associations/shared/association-service.ts b/src/associations/shared/association-service.ts index f796d879..c5743443 100644 --- a/src/associations/shared/association-service.ts +++ b/src/associations/shared/association-service.ts @@ -28,7 +28,7 @@ export function getPreparedAssociationOptions(optionsOrForeignKey?: string | Non * Stores association meta data for specified class */ export function addAssociation(target: any, - association: BaseAssociation) { + association: BaseAssociation) { let associations = getAssociations(target); @@ -54,7 +54,7 @@ export function setAssociations(target: a } export function getAssociationsByRelation(target: any, - relatedClass: any): BaseAssociation[] { + relatedClass: any): BaseAssociation[] { const associations = getAssociations(target); return (associations || []).filter(association => { const _relatedClass = association.getAssociatedClass(); From 09833f2311c9c905cbc34d83b1865ac2565361bd Mon Sep 17 00:00:00 2001 From: KapitanOczywisty <44417092+KapitanOczywisty@users.noreply.github.com> Date: Sat, 6 Feb 2021 12:07:17 +0100 Subject: [PATCH 3/6] Suppress internal Model type error --- .../belongs-to-many/belongs-to-many-association.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/associations/belongs-to-many/belongs-to-many-association.ts b/src/associations/belongs-to-many/belongs-to-many-association.ts index 9045092b..c5ad88a0 100644 --- a/src/associations/belongs-to-many/belongs-to-many-association.ts +++ b/src/associations/belongs-to-many/belongs-to-many-association.ts @@ -29,8 +29,8 @@ export class BelongsToManyAssociation ext const throughModel = typeof throughOptions === 'object' && typeof throughOptions.model !== "string" ? throughOptions.model : undefined; options.through = throughOptions; - options.foreignKey = getForeignKeyOptions(model, throughModel, this.options.foreignKey); - options.otherKey = getForeignKeyOptions(associatedClass, throughModel, this.options.otherKey); + options.foreignKey = getForeignKeyOptions(model, throughModel as any, this.options.foreignKey); + options.otherKey = getForeignKeyOptions(associatedClass, throughModel as any, this.options.otherKey); return options; } From d23da07155cd765f66b46fe576224268e39f4de5 Mon Sep 17 00:00:00 2001 From: KapitanOczywisty <44417092+KapitanOczywisty@users.noreply.github.com> Date: Sat, 6 Feb 2021 18:01:54 +0100 Subject: [PATCH 4/6] Fix BelongsToMany to accept parameters for through model --- .../belongs-to-many-association.ts | 15 ++++++----- .../belongs-to-many-options.ts | 4 +-- .../belongs-to-many/belongs-to-many.ts | 25 ++++++++++--------- .../foreign-key/foreign-key-service.ts | 6 ++--- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/associations/belongs-to-many/belongs-to-many-association.ts b/src/associations/belongs-to-many/belongs-to-many-association.ts index c5ad88a0..9dfacb5a 100644 --- a/src/associations/belongs-to-many/belongs-to-many-association.ts +++ b/src/associations/belongs-to-many/belongs-to-many-association.ts @@ -1,5 +1,3 @@ -import {BelongsToManyOptions as OriginBelongsToManyOptions, ThroughOptions} from "sequelize"; - import {BaseAssociation} from '../shared/base-association'; import {BelongsToManyOptions} from './belongs-to-many-options'; import {ModelNotInitializedError} from '../../model/shared/model-not-initialized-error'; @@ -9,11 +7,12 @@ import {Association} from "../shared/association"; import {Sequelize} from "../../sequelize/sequelize/sequelize"; import {UnionAssociationOptions} from "../shared/union-association-options"; import {ModelType} from "../../model/model/model"; +import {ThroughOptions} from "../through/through-options"; -export class BelongsToManyAssociation extends BaseAssociation { +export class BelongsToManyAssociation extends BaseAssociation { constructor(associatedClassGetter: ModelClassGetter, - protected options: BelongsToManyOptions) { + protected options: BelongsToManyOptions) { super(associatedClassGetter, options); } @@ -23,7 +22,7 @@ export class BelongsToManyAssociation ext getSequelizeOptions(model: ModelType, sequelize: Sequelize): UnionAssociationOptions { - const options: OriginBelongsToManyOptions = {...this.options as any}; + const options: BelongsToManyOptions = {...this.options}; const associatedClass = this.getAssociatedClass(); const throughOptions = this.getThroughOptions(sequelize); @@ -35,10 +34,10 @@ export class BelongsToManyAssociation ext return options; } - private getThroughOptions(sequelize: Sequelize): ThroughOptions | string { + private getThroughOptions(sequelize: Sequelize): ThroughOptions | string { const through = this.options.through; const throughModel = typeof through === 'object' ? through.model : through; - const throughOptions: ThroughOptions = + const throughOptions: ThroughOptions = typeof through === 'object' ? {...through} : {} as any; if (typeof throughModel === 'function') { @@ -46,7 +45,7 @@ export class BelongsToManyAssociation ext if (!throughModelClass.isInitialized) { throw new ModelNotInitializedError(throughModelClass, 'Association cannot be resolved.'); } - throughOptions.model = throughModelClass; + throughOptions.model = throughModelClass as any; } else { return throughModel; } diff --git a/src/associations/belongs-to-many/belongs-to-many-options.ts b/src/associations/belongs-to-many/belongs-to-many-options.ts index 895b1300..cdecb506 100644 --- a/src/associations/belongs-to-many/belongs-to-many-options.ts +++ b/src/associations/belongs-to-many/belongs-to-many-options.ts @@ -3,8 +3,8 @@ import {ModelClassGetter} from "../../model/shared/model-class-getter"; import {ThroughOptions} from "../through/through-options"; -export type BelongsToManyOptions = { +export type BelongsToManyOptions = { [K in keyof OriginBelongsToManyOptions]: K extends 'through' - ? ModelClassGetter | string | ThroughOptions + ? ModelClassGetter | string | ThroughOptions : OriginBelongsToManyOptions[K] }; diff --git a/src/associations/belongs-to-many/belongs-to-many.ts b/src/associations/belongs-to-many/belongs-to-many.ts index 59e0285c..a9f826e9 100644 --- a/src/associations/belongs-to-many/belongs-to-many.ts +++ b/src/associations/belongs-to-many/belongs-to-many.ts @@ -3,19 +3,20 @@ import {BelongsToManyAssociation} from './belongs-to-many-association'; import {ModelClassGetter} from "../../model/shared/model-class-getter"; import {addAssociation} from "../shared/association-service"; -export function BelongsToMany(associatedClassGetter: ModelClassGetter, - through: ModelClassGetter | string, - foreignKey?: string, - otherKey?: string): Function; -export function BelongsToMany(associatedClassGetter: ModelClassGetter, - options: BelongsToManyOptions): Function; -export function BelongsToMany(associatedClassGetter: ModelClassGetter, - throughOrOptions: ModelClassGetter | string | BelongsToManyOptions, - foreignKey?: string, - otherKey?: string): Function { +export function BelongsToMany< + TCreationAttributes, TModelAttributes, TCreationAttributesThrough, TModelAttributesThrough>(associatedClassGetter: ModelClassGetter, + through: ModelClassGetter | string, + foreignKey?: string, + otherKey?: string): Function; +export function BelongsToMany(associatedClassGetter: ModelClassGetter, + options: BelongsToManyOptions): Function; +export function BelongsToMany(associatedClassGetter: ModelClassGetter, + throughOrOptions: ModelClassGetter | string | BelongsToManyOptions, + foreignKey?: string, + otherKey?: string): Function { return (target: any, propertyName: string) => { - let options: Partial> = {foreignKey, otherKey}; + let options: Partial> = {foreignKey, otherKey}; if (typeof throughOrOptions === 'string' || typeof throughOrOptions === 'function') { @@ -28,7 +29,7 @@ export function BelongsToMany(associatedC addAssociation(target, new BelongsToManyAssociation( associatedClassGetter, - options as BelongsToManyOptions, + options as BelongsToManyOptions, ) ); }; diff --git a/src/associations/foreign-key/foreign-key-service.ts b/src/associations/foreign-key/foreign-key-service.ts index e4ee7b93..f630268f 100644 --- a/src/associations/foreign-key/foreign-key-service.ts +++ b/src/associations/foreign-key/foreign-key-service.ts @@ -6,9 +6,9 @@ import {ModelType} from "../../model/model/model"; const FOREIGN_KEYS_KEY = 'sequelize:foreignKeys'; -export function getForeignKeyOptions(relatedClass: ModelType, - classWithForeignKey?: ModelType, - foreignKey?: string | ForeignKeyOptions): ForeignKeyOptions { +export function getForeignKeyOptions(relatedClass: ModelType, + classWithForeignKey?: ModelType, + foreignKey?: string | ForeignKeyOptions): ForeignKeyOptions { let foreignKeyOptions: ForeignKeyOptions = {}; if (typeof foreignKey === 'string') { From 164e6582618df4afdbc09f5540f3b28b1600051a Mon Sep 17 00:00:00 2001 From: KapitanOczywisty <44417092+KapitanOczywisty@users.noreply.github.com> Date: Sat, 6 Feb 2021 18:10:09 +0100 Subject: [PATCH 5/6] Add test for models with attributes --- test/types/attributes.spec.ts | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 test/types/attributes.spec.ts diff --git a/test/types/attributes.spec.ts b/test/types/attributes.spec.ts new file mode 100644 index 00000000..2a9b7f7f --- /dev/null +++ b/test/types/attributes.spec.ts @@ -0,0 +1,73 @@ +// Types only test. This should compile successfully. + +import { Optional } from "sequelize"; +import { + AutoIncrement, + BelongsTo, + BelongsToMany, + ForeignKey, +} from "../../src/index"; +import { Column } from "../../src/model/column/column"; +import { Model } from "../../src/model/model/model"; +import { Table } from "../../src/model/table/table"; +import { DataType } from "../../src/sequelize/data-type/data-type"; + +interface PetPersonAttributes { + petId: number; + personId: number; +} + +@Table +class PetPerson extends Model { + @ForeignKey(() => Pet) + @Column + petId: number; + + @ForeignKey(() => Person) + @Column + personId: number; +} + +interface PersonAttributes { + id: number; + name: string; +} +type PersonCreationAttributes = Optional; + +@Table +export class Person extends Model { + @AutoIncrement + @Column(DataType.INTEGER) + id: number; + + @Column(DataType.STRING) + name: string; +} + +@Table +export class Pet extends Model { + @AutoIncrement + @Column(DataType.INTEGER) + petId: number; + + @Column(DataType.STRING) + name: string; + + // model with attributes + @BelongsToMany(() => Person, () => PetPerson) + owners: Person[]; +} + +@Table +export class Toy extends Model { + @ForeignKey(() => Pet) + @Column(DataType.INTEGER) + petId: number; + + @Column(DataType.STRING) + name: string; + + // model without attributes + @BelongsTo(() => Pet) + pet: Pet; +} From c65f875a88a1395286604e2df05a434bf622347c Mon Sep 17 00:00:00 2001 From: KapitanOczywisty <44417092+KapitanOczywisty@users.noreply.github.com> Date: Sun, 7 Feb 2021 13:43:52 +0100 Subject: [PATCH 6/6] Fix ModelCtor definition --- src/model/model/model.ts | 3 ++- src/sequelize/sequelize/sequelize.ts | 2 +- test/types/attributes.spec.ts | 9 +++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/model/model/model.ts b/src/model/model/model.ts index 86f38d53..63be8d12 100644 --- a/src/model/model/model.ts +++ b/src/model/model/model.ts @@ -7,9 +7,10 @@ import {AssociationGetOptions} from "./association/association-get-options"; import {AssociationCountOptions} from "./association/association-count-options"; import {AssociationActionOptions} from "./association/association-action-options"; import {AssociationCreateOptions} from "./association/association-create-options"; +import {Repository} from '../../sequelize/repository/repository'; export type ModelType = new (values?: TCreationAttributes, options?: any) => Model; -export type ModelCtor = (new () => M) & typeof Model; +export type ModelCtor = Repository; export type $GetType = NonNullable extends any[] ? NonNullable : (NonNullable | null); diff --git a/src/sequelize/sequelize/sequelize.ts b/src/sequelize/sequelize/sequelize.ts index 86d4fd2b..868f4fea 100644 --- a/src/sequelize/sequelize/sequelize.ts +++ b/src/sequelize/sequelize/sequelize.ts @@ -110,7 +110,7 @@ export class Sequelize extends OriginSequelize { } private createRepositoryModel(modelClass: ModelCtor): ModelCtor { - return class extends modelClass { + return class extends modelClass { }; } diff --git a/test/types/attributes.spec.ts b/test/types/attributes.spec.ts index 2a9b7f7f..155859f1 100644 --- a/test/types/attributes.spec.ts +++ b/test/types/attributes.spec.ts @@ -6,6 +6,8 @@ import { BelongsTo, BelongsToMany, ForeignKey, + PrimaryKey, + Sequelize, } from "../../src/index"; import { Column } from "../../src/model/column/column"; import { Model } from "../../src/model/model/model"; @@ -36,6 +38,7 @@ type PersonCreationAttributes = Optional; @Table export class Person extends Model { + @PrimaryKey @AutoIncrement @Column(DataType.INTEGER) id: number; @@ -46,6 +49,7 @@ export class Person extends Model { @Table export class Pet extends Model { + @PrimaryKey @AutoIncrement @Column(DataType.INTEGER) petId: number; @@ -71,3 +75,8 @@ export class Toy extends Model { @BelongsTo(() => Pet) pet: Pet; } + +function testTypes() { + // all models should be accepted + new Sequelize().addModels([Person, Pet, PetPerson]); +}