sequelize-typescript: Type 'typeof Player' is not assignable to type 'typeof Model'

Versions

  • sequelize: sequelize@6.3.5
  • sequelize-typescript: sequelize-typescript@1.1.0
  • typescrip: typescript@4.0.2

I’m submitting a …

[X] bug report [ ] feature request

Actual behavior: I have added 2 class files, Player.ts and Team.ts as per the example. In each of the references:

  @HasMany(() => Player)

and

  @ForeignKey(() => Team)
  @Column
  teamId: number;
 
  @BelongsTo(() => Team)
  team: Team;

The Team and the Player following the => on the attribute is underlines in red in VS code with the error:

Type 'typeof Team' is not assignable to type 'typeof Model'.
  Construct signature return types 'Team' and 'Model<T, T2>' are incompatible.
    The types of '_attributes' are incompatible between these types.
      Type 'Team' is not assignable to type 'T'.
        'T' could be instantiated with an arbitrary type which could be unrelated to 'Team'.ts(2322)
model-class-getter.d.ts(2, 40): The expected type comes from the return type of this signature.

Expected behavior: No Errors

Steps to reproduce: Added Player.ts with the sample code provided in the readme.md, and Team.ts in the same way

Related code: Player.ts

import { Table, Model, Column, ForeignKey, BelongsTo } from 'sequelize-typescript'

@Table
export class Player extends Model<Player> {
 
  @Column
  name: string;
 
  @Column
  num: number;
 
  @ForeignKey(() => Team)
  @Column
  teamId: number;
 
  @BelongsTo(() => Team)
  team: Team;
}

Team.ts

import { Table, Model, Column, ForeignKey, HasMany } from 'sequelize-typescript'
import { Player } from './Player';


@Table
export class Team extends Model<Team> {
 
  @Column
  name: string;
 
  @HasMany(() => Player)
  players: Player[];
}

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 3
  • Comments: 20 (5 by maintainers)

Most upvoted comments

You can use sequelize^6.3.5 + sequelize-typescript^2.0.0-beta.1, you only need to remove argument from Model<...>:

-export class Team extends Model<Team> {
+export class Team extends Model {

Thanks to @lukashroch for updated docs: https://github.com/lukashroch/sequelize-typescript/tree/sequelize6-docs#v6-model-definition-less-strict

It’s related to sequelize@6.3.5. I have the same issue with both sequelize-typescript @1.1.0 & @2.0.0-beta.0

If I downgrade to sequelize@5.22.0 the issue is gone.

It must be a change in the sequelize Model type which is not compatible with the decorators typing.

Already reported in: #828, #826, #821 #813

Looks like using sequelize@6.1.1 solve the issue for now, which is the last version of sequelize with Model type compatible with sequelize-typescript.

I have the same problem with

"sequelize": "^6.3.5",
"sequelize-typescript": "^2.0.0-beta.0"

and

"sequelize": "^6.1.1",
"sequelize-typescript": "^2.0.0-beta.0"

resolved with downgrade to

"sequelize": "^5.22.0",
"sequelize-typescript": "^1.1.0"

Thanks your proposal can solve the issue

I have been rewriting an old pure js code to ts and have got this error. The issue was that I had used the Model class from the sequelize package instead of the Model class from the sequelize-typescript package.

Same here, @RobinBuschmann any idea what’s going on?

Hello, similar to the approach outlined above, has anyone been able to build something with private declarations and a constructor model?

    import {Column, DataType, Model, Table} from 'sequelize-typescript';

@Table({
  timestamps: false,
  freezeTableName: true,
  tableName: 'author'
})
export class Author extends Model<Author> {
  
  @Column({
    type: DataType.NUMBER,
    allowNull: false,
    field: 'id',
    primaryKey: true,
  })
  private _id: Number;
  
  @Column({
    type: DataType.STRING,
    allowNull: false,
    field: 'name',
  })
  private _name: string;
  
  @Column({
    type: DataType.STRING,
    allowNull: false,
    field: 'code',
  })
  private _code: string;

  @Column({
    type: DataType.STRING,
    allowNull: false,
    field: 'created_at',
  })
  private _createdAt: Date;

  constructor(id: Number, name: string, code: string) {
    super();
    this._id = id;
    this._name = name;
    this._code = code;
    this._createdAt = new Date();
  }

  public updateAuthor(name: string, code: string) {
    this._name = name;
    this._code = code;
  }

  get id(): Number {
    return this._id;
  }

  get name(): string {
    return this._name;
  }

  get code(): string {
    return this._code;
  }

}

I would love to build a rich DDD style model, but I keep getting this error:

The ‘this’ context of type ‘typeof Author’ is not assignable to method’s ‘this’ of type ‘(new () => Author) & typeof Model’. Type ‘typeof Author’ is not assignable to type ‘new () => Author’.

Would love to see if someone has tried similar approaches.

Hello @Austine105, did you found any solution for this issue ? I have the same problem with nest.js

For people wondering in which release this issue was resolved in sequelize: v6.6.1

I’m not sure if the above fixes the problem with Includeables:

PaymentCard.findOne({
  transaction,
  include: [BillingAddress],
  where: { active: true },
}),

Gives:

No overload matches this call.
  Overload 1 of 2, '(this: ModelStatic<PaymentCard>, options: NonNullFindOptions<PaymentCardAttrs>): Promise<PaymentCard>', gave the following error.
    Type 'typeof BillingAddress' is not assignable to type 'Includeable'.
      Type 'typeof BillingAddress' is not assignable to type 'typeof Model'.
        Types of construct signatures are incompatible.
          Type 'new (values?: BillingAddressCreateAttrs, options?: BuildOptions) => BillingAddress' is not assignable to type 'new <TModelAttributes extends {} = any, TCreationAttributes extends {} = TModelAttributes>(values?: TCreationAttributes, options?: BuildOptions) => Model<TModelAttributes, TCreationAttributes>'.
            Types of parameters 'values' and 'values' are incompatible.
              Type 'TCreationAttributes' is not assignable to type 'BillingAddressCreateAttrs'.
                Type '{}' is missing the following properties from type 'BillingAddressCreateAttrs': paymentCardId, name, lastName, address1, and 6 more.
  Overload 2 of 2, '(this: ModelStatic<PaymentCard>, options?: FindOptions<PaymentCardAttrs>): Promise<PaymentCard>', gave the following error.
    Type 'typeof BillingAddress' is not assignable to type 'Includeable'.
      Type 'typeof BillingAddress' is not assignable to type 'typeof Model'.ts(2769)

And I think it’s the initial problem I mentioned in my original PR. That Sequelize has it’s own Model types that we’d need to override somehow.

It works if you remove the Attrs and CreateAttr types:

@Table
export class PaymentCard extends Model {
  @HasOne(() => BillingAddress)
  public billingAddress: BillingAddress;
}

@Table
export class BillingAddress extends Model {...}

@KapitanOczywisty solution also works with:

  • "sequelize": "^6.5.0",
    
  • "sequelize-typescript": "^2.1.0"
    

So i think we can work free with the latest versions

Yes I did.

I used the factory pattern to configure sequelize as a provider and inject them in each module.

// database.providers.ts
export const databaseProviders = [
    {
        provide: SEQUELIZE, //  'SEQUELIZE'
        useFactory: async () => {
          const sequelize = new Sequelize(configService.getSequelizeConfig());
            sequelize.addModels([UserModel, OtherModels..]);
            await sequelize.sync();
            return sequelize;
        },
    },
];
// database.module.ts
@Module({
    providers: [...databaseProviders],
    exports: [...databaseProviders],
})
export class DatabaseModule { }

import DatabaseModule in your app.module file. In a module, e.g UserModule, create the file below:

// user.provider.ts
export const UserProvider = [
  {
    provide: USER_REPOSITORY,  // 'USER_REPOSITORY'
    useValue: UserModel,
  }
];

Add the provider to UserModule

// user.module.ts
...imports...
providers: [UserService, ...UserProvider],  // the spread operator in UserProvider is intentional
...exports...

Finally in UserService constructor

// user.service.ts
constructor(
    @Inject(USER_REPOSITORY) private readonly userRepo: typeof UserModel
  ) { }


// in your methods, you can now use the userRepo, e.g this.userRepo.findAndCountAll(query...)

It’s related to sequelize@6.3.5. I have the same issue with both sequelize-typescript @1.1.0 & @2.0.0-beta.0

If I downgrade to sequelize@5.22.0 the issue is gone.

It must be a change in the sequelize Model type which is not compatible with the decorators typing.

Already reported in: #828, #826, #821 #813

Looks like using sequelize@6.1.1 solve the issue for now, which is the last version of sequelize with Model type compatible with sequelize-typescript.

using sequelize@6.1.1 actually solves the issue, but creates another issue. It messes with the dependency injection in when using NestJS, the error is given as:

Type '(attributes: ModelAttributes<Model<any, any>>, options: InitOptions<Model<any, any>>) => void' is not assignable to type '<M extends Model<any, any> = Model<any, any>>(this: ModelCtor<M>, attributes: ModelAttributes<M>, options: InitOptions<M>) => Model<...>'.ts(2684)