sequelize-typescript icon indicating copy to clipboard operation
sequelize-typescript copied to clipboard

Changes in sequelize to avoid calling model function overrides break alias-inference logic

Open toddbaert opened this issue 4 years ago • 8 comments

I believe https://github.com/sequelize/sequelize/commit/b253d8ed63c91bc2c7143f07806554b5a5ac67eb breaks the alias-inference logic in sequelize-typescript. I believe this is because this change breaks the proxy behavior that sequelize-typescript relies on.

I have opened an issue with sequelize as well: https://github.com/sequelize/sequelize/issues/14003

Issue

Versions

  • sequelize: 6.14
  • sequelize-typescript: 2.1.2
  • typescript: 4.5.5

Issue type

  • [x] bug report

Actual behavior

I have defined no alias in my decorators. My model x simply belongs to y:

  @BelongsTo(() => y, {
    foreignKey: {
      field: 'y_id',
      name: 'yId'
    }
  })

GeneralError: x is associated to y using an alias. You must use the 'as' keyword to specify the alias within your include statement.

Expected behavior

Alias inference works.

Related code

https://github.com/RobinBuschmann/sequelize-typescript/blob/b60c011be2e971e56cb783d4ade994965faab916/src/model/model/model.ts#L209

toddbaert avatar Jan 24 '22 17:01 toddbaert

This change has been reverted in v6 but it's still landing in v7 I'm not sure what the alias-inference logic does but if it makes sense to have it upstream, I think we'd welcome it. That'd avoid this issue :)

ephys avatar Jan 25 '22 14:01 ephys

Typing needs to be updated for more than just this situation. Hopefully we get an update soon!

kamronbatman avatar Feb 05 '22 22:02 kamronbatman

What do you mean? The change has already been reverted

ephys avatar Feb 06 '22 09:02 ephys

I must be speaking of a different issue, since this simple example is broken with sequelize >= 6.14. I was generalizing that there were updates that changing the typing of sequelize itself.

  async create(user: UserDto): Promise<User> {
    return this.userRepository.create<User>(user);
  }

kamronbatman avatar Feb 06 '22 17:02 kamronbatman

Can you post the TS error you're having?

ephys avatar Feb 07 '22 10:02 ephys

@ephys UserDto is not assignable to type CreateAttributes<User> And this started with 6.14.

The typing got more strict, so the class definition I had was no longer "valid".

export class User extends Model<User>

has to be

export class User extends Model<User, Partial<User>>

or something like

export class User extends Model<User, UserCreationDto>

Sorry for hijacking this issue, since it is definitely unrelated.

kamronbatman avatar Feb 14 '22 00:02 kamronbatman

@kamronbatman very late with my reply but yes, we're changing how models are typed. This is a change from upstream Sequelize. It's very unfortunate that it lead to an error on your end. We felt this feature was well worth bringing into Sequelize 6 and we did our best to avoid typing breaking changes, but any typing change can have hard to predict consequences

I would recommend looking at our new InferAttributes and InferCreationAttributes. Their introduction is what caused your issue but it should help improve your typings :)

They should be compatible with sequelize-typescript

ephys avatar Apr 07 '22 13:04 ephys

I'm not sure my issue is the same as this one, but at least it may be related.

When I define a relation like this (following the readme):

@Table({ tableName: 'classCategories' })
export default class ClassCategory extends BaseModel<ClassCategoryAttributes, ClassCategoryCreateAttributes> {
  @Column(DataType.STRING)
  declare name: string;

  @Column(DataType.STRING)
  declare tag: string;

  @HasMany(() => ClassSubcategory)
  declare classSubcategories: ClassSubcategory[];
}

@Table({ tableName: 'classSubcategories' })
export default class ClassSubcategory extends BaseModel<ClassSubcategoryAttributes, ClassSubcategoryCreateAttributes> {
  @Column(DataType.STRING)
  declare name: string;

  @Column(DataType.STRING)
  declare tag: string;

  @ForeignKey(() => ClassCategory)
  @Column(DataType.UUID)
  declare classCategoryId: string;

  @BelongsTo(() => ClassCategory)
  declare classCategory: ClassCategory;
}

And try to create an instance, I get the following error:

ClassSubcategory is associated to ClassCategory using an alias. You must use the 'as' keyword to specify the alias within your include statement.

Though no alias is defined. Is it a bug, or is there something wrong with my code?

evenfrost avatar Mar 25 '24 12:03 evenfrost