Sequelize-Typescript typeof model
Asked Answered
J

3

8

I'm trying to create a base crud service that takes a Sequelize model and creates all basic APIs for it so what I have done it this:

export class RepositoryService<T extends Model<T>> {
  constructor(protected model: typeof Model) {
  }
  public async getMany(
    query: RequestParamsParsed = {},
    options: RestfulOptions = {},
  ): Promise<T[]> {
    return this.model.findAll();
  }
}

I'm getting the following error:

The 'this' context of type 'typeof Model' is not assignable to method's 'this' of type 'new () => Model<Model<any>>'.
  Cannot assign an abstract constructor type to a non-abstract constructor type.

this is because of this line in the seqeulize-typescript package:

static findAll<T extends Model<T>>(this: (new () => T), options?: IFindOptions<T>): Promise<T[]>;

I'm relatively new to Typescript so if anyone can tell me what's the meaning of this: (new () => T) in the findAll function and how can I work this out.

Johnniejohnny answered 14/3, 2019 at 15:23 Comment(1)
arg: (new () => T) means that arg is not instance of type T like in (arg: T). arg is class T. Also you can use this syntax for that (arg: { new (...args): T })Natatorial
J
2

The problem seemed to be in this line

constructor(protected model: typeof Model) {}

The Model I was setting the model type to is imported from sequelize-typescript while I should use the original model exported from sequelize itself.

The whole code is like this:

import { Model as OriginalModel } from 'sequelize';
import { Model } from 'sequelize-typescript';
export class RepositoryService<T extends Model<T>> {
  constructor(protected model: typeof OriginalModel) {
  }
  public async getMany(
    query: RequestParamsParsed = {},
    options: RestfulOptions = {},
  ): Promise<T[]> {
    return this.model.findAll();
  }
}
Johnniejohnny answered 17/3, 2019 at 20:22 Comment(1)
Better solution from @Elmiraelmo below.Roland
E
6

Also encountered this error while working with the sequelize-typescript library.

You could first define these helper types:

import { Model } from "sequelize-typescript";

// Type `ModelType` would basically wrap & satisfy the 'this' context of any sequelize helper methods
type Constructor<T> = new (...args: any[]) => T;
type ModelType<T extends Model<T>> = Constructor<T> & typeof Model;

Then, use it with your code:

export class RepositoryService<T extends Model<T>> {
  constructor(protected model: ModelType<T>) {}

  public async getMany(
    query: RequestParamsParsed = {},
    options: RestfulOptions = {},
  ): Promise<T[]> {
    return this.model.findAll();
  }
}

Hope this helps.

Elmiraelmo answered 6/1, 2020 at 9:44 Comment(0)
J
2

The problem seemed to be in this line

constructor(protected model: typeof Model) {}

The Model I was setting the model type to is imported from sequelize-typescript while I should use the original model exported from sequelize itself.

The whole code is like this:

import { Model as OriginalModel } from 'sequelize';
import { Model } from 'sequelize-typescript';
export class RepositoryService<T extends Model<T>> {
  constructor(protected model: typeof OriginalModel) {
  }
  public async getMany(
    query: RequestParamsParsed = {},
    options: RestfulOptions = {},
  ): Promise<T[]> {
    return this.model.findAll();
  }
}
Johnniejohnny answered 17/3, 2019 at 20:22 Comment(1)
Better solution from @Elmiraelmo below.Roland
A
2

Using "sequelize-typescript": "2.1.0" you can use ModelCtor provided by the module eg.

import { Model, ModelCtor } from 'sequelize-typescript';

export class RepositoryService<T extends Model<T>> {
  constructor(protected model: ModelCtor<T>) {}

  public async getMany(
    query: RequestParamsParsed = {}, 
    options: RestfulOptions = {}
): Promise<T[]> {
    return this.model.findAll();
  }
}

The ModelCtor type is:

export declare type Repository<M> = (new () => M) & NonAbstract<typeof Model>;

export declare type ModelCtor<M extends Model = Model> = Repository<M>;

Affect answered 26/6, 2021 at 3:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.