Sequelize-typescript: Passing a model to a function and accessing static members

Created on 12 Dec 2017  路  4Comments  路  Source: RobinBuschmann/sequelize-typescript

I'm trying to write a function that takes a model class and calls .findAll({}), but TypeScript is giving me an error. This reproduces it:

async function createResource(model: typeof Model) {
  const results = await model.findAll({})
}

gives:

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

Most helpful comment

You can achieve this like so:

type NonAbstract<T> = {[P in keyof T]: T[P]}; // "abstract" gets lost here
type Constructor<T> = (new () => T);
type NonAbstractTypeOfModel<T> = Constructor<T> & NonAbstract<typeof Model>;

function createResource<T extends Model<T>>(model: NonAbstractTypeOfModel<T>): Promise<T[]> {
    return model.findAll<T>();
}

Now you can use it without passing any generic type explicitly. The proper type is inferred automatically by typescript:

createResource(User)
    .then(users => users[0]. ...) // <-- autocompletion should work very well here
;

All 4 comments

Seems this might be a deeper issue in TypeScript: https://github.com/Microsoft/TypeScript/issues/5843#issuecomment-348356421

You can achieve this like so:

type NonAbstract<T> = {[P in keyof T]: T[P]}; // "abstract" gets lost here
type Constructor<T> = (new () => T);
type NonAbstractTypeOfModel<T> = Constructor<T> & NonAbstract<typeof Model>;

function createResource<T extends Model<T>>(model: NonAbstractTypeOfModel<T>): Promise<T[]> {
    return model.findAll<T>();
}

Now you can use it without passing any generic type explicitly. The proper type is inferred automatically by typescript:

createResource(User)
    .then(users => users[0]. ...) // <-- autocompletion should work very well here
;

How obvious, thanks! This solves my issue, but FYI, yours gives:

Type 'Bluebird<T[]>' is not assignable to type 'Promise<T[]>'.
  Property '[Symbol.toStringTag]' is missing in type 'Bluebird<T[]>'.

So you need to return model.findAll<T>() as any as Promise<T[]>.

You need to use bluebird as the promise type:
import * as Promise from 'bluebird' Then the error disappears as well :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bschveitzer picture bschveitzer  路  5Comments

ReneHollander picture ReneHollander  路  3Comments

thestrayed picture thestrayed  路  5Comments

fareshan picture fareshan  路  4Comments

fareshan picture fareshan  路  3Comments