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

Model.build(), Model.create(), modelInstance.set() do not accept an object with an association.

Open maqduni opened this issue 3 years ago • 5 comments

Issue

Following methods do not accept an object with an association,

  • Model.build()
  • Model.create()
  • modelInstance.set()

Versions

  • sequelize: 6.21.2
  • sequelize-typescript: 2.1.3
  • typescript: 4.7.4

Issue type

  • [x] bug report
  • [ ] feature request

Actual behavior

Getting the following compiler error, TS2345: Argument of type '{ email: string; role: Role; memberProfile: { interests: string[]; }; firstName: string; lastName: string; }' is not assignable to parameter of type 'Optional<User, NullishPropertiesOf<User>>'.   Type '{ email: string; role: Role; memberProfile: { cohort: string; }; firstName: string; lastName: string; }' is not assignable to type 'Partial<Pick<User, NullishPropertiesOf<User>>>'.     Types of property 'memberProfile' are incompatible.       Type '{ interests: string[]; }' is missing the following properties from type 'MemberProfile': userId, $add, and 35 more.

Expected behavior

Should be able to pass an object with an association. Would like the initial data object type to be similar to RecursivePartial<>, i.e. RecursiveNullishPropertiesOf<>

Steps to reproduce

Please use the code below to reproduce.

Related code

export class User extends Model<User> {
  @Column
  public email: string;

  @Column
  public role: Role;

  @Column
  public firstName?: string;

  @Column
  public lastName?: string;

  @HasOne(() => MemberProfile, 'userId')
  public memberProfile?: MemberProfile;
}

export class MemberProfile extends Model<MemberProfile> {
  @Column
  userId: number;

  @Column
  interests?: string[];
}

const seedUser = {
  email: '[email protected]',
  role: Role.member,
  memberProfile: {
    interests: ['soccer', 'cooking'],
  },
  firstName: 'Christiano',
  lastName: 'Ronaldo',
};

const newUser = User.build(seedUser);

maqduni avatar Jul 30 '22 19:07 maqduni

Try create a interface for model attributes. E.g:

interface UserAttributes {
  email: string;
  role: Role;
  firstName?: string;
  lastName?: string;
}

class User extends Model<UserAttributes> {
  /* code */
}

It works for me.

cHenrique0 avatar Aug 08 '22 21:08 cHenrique0

Try create a interface for model attributes. E.g:

interface UserAttributes {
  email: string;
  role: Role;
  firstName?: string;
  lastName?: string;
}

class User extends Model<UserAttributes> {
  /* code */
}

It works for me.

The problem is when you have an association in your interface. Simple data types work in my set up as well. And my model uses itself as an interface export class User extends Model<User> {

maqduni avatar Aug 09 '22 02:08 maqduni

you probably want to declare models like this: https://github.com/RobinBuschmann/sequelize-typescript#model-definition

your example code is usingexport class User extends Model<User>, which is definition for sequelize v5

broxiang avatar Feb 20 '23 16:02 broxiang

you can change your code to export class User extends Model {}

broxiang avatar Feb 20 '23 16:02 broxiang

you can change your code to export class User extends Model {}

Just to optimize the search, Fixes for errors TS2740 and TS2322

oktapodia avatar Jul 21 '23 10:07 oktapodia