types/sequelize

[TypeScript] Typing the Promise returned by a query

Closed this issue · 1 comments

Using TypeScript in my application, I have a UserModel defined like this:

import { Instance } from 'sequelize';

interface IUserAttributes {
  id: number;
  first_name: string;
  last_name: string;
  ...
}

type UserModel = Instance<IUserAttributes> & IUserAttributes;

All good till there. I want to type the function I to query users:

const findUsers = () => db.User.findAll();
const findUserById = (id: number) => db.User.findById(id);

My first try was:

const findUsers = (): Promise<UserModel[]> => db.User.findAll();
const findUserById = (id: number): Promise<UserModel | null> => db.User.findById(id);

I got the following errors:

error TS2322: Type 'Bluebird<{}[]>' is not assignable to type 'Promise<UserModel[]>'.
error TS2322: Type 'Bluebird<{} | null>' is not assignable to type 'Promise<UserModel | null>'.

Okay, so I tried:

import * as Bluebird from 'bluebird';

const findUsers = (): Bluebird<UserModel[]> => db.User.findAll();
const findUserById = (id: number): Bluebird<UserModel | null> => db.User.findById(id);

I got this errors:

error TS2322: Type 'Bluebird<{}[]>' is not assignable to type 'Bluebird<UserModel[]>'.
error TS2322: Type 'Bluebird<{} | null>' is not assignable to type 'Bluebird<UserModel | null>'.

Keep trying:

import * as Bluebird from 'bluebird';

const findUsers = (): Bluebird<UserModel[]> => db.User.findAll() as Bluebird<UserModel[]>;
const findUserById = (id: number): Bluebird<UserModel | null> => db.User.findById(id) as Bluebird<UserModel | null>;

One of them is working, but the promise returning the array of Model still fail:

error TS2352: Type 'Bluebird<{}[]>' cannot be converted to type 'Bluebird<UserModel[]>'.

At this point I'm not really sure anymore what to do. In my last resort I used PromiseLike instead of Bluebird:

const findUsers = (): PromiseLike<UserModel[]> => db.User.findAll();
const findUserById = (id: number): PromiseLike<UserModel | null> => db.User.findById(id);

However now I cannot use .catch() now:

error TS2339: Property 'catch' does not exist on type 'PromiseLike'.

Please help, I was surprise to not find anything about this :/

It's usually when you post something that you find the solution. Turns out that you just need to type the model correctly. I had the following:

import Sequelize from 'sequelize';

interface IModelsObject {
  User: Sequelize.Model<{},{}>;
}

const models: IModelsObject = {
  User: sequelize.import(`${modelPath}/User`),
};

I just updated it like this:

interface IModelsObject {
  User: Sequelize.Model<UserModel, IUserAttributes>;
}

const models: IModelsObject = {
  User: sequelize.import(`${modelPath}/User`),
};

I hope this help someone some day...