class fields are shadowing Sequelize's attribute getters & setters

See original GitHub issue

Issue

Versions

  • sequelize: ^6.17.0
  • sequelize-typescript: ^2.1.3
  • typescript: ^4.5.4
  • fastify: ^3.0.0

Issue type

  • bug report

Actual behavior

[App] (sequelize) Warning: Model "Users" is declaring public class fields for attribute(s): "firstName", "lastName", "email", "userName", "phone", "dob", "password", "role_id", "role_title".
[App] These class fields are shadowing Sequelize's attribute getters & setters.
[App] See https://sequelize.org/main/manual/model-basics.html#caveat-with-public-class-field

Expected behavior

a clean CLI log without this warning, what am i doing wrong.

Steps to reproduce

I created simple models with annotations and use their objects to save or retrieve data from the database

Related code

model

import {Table, Column, Model, DataType, Unique, BelongsToMany} from 'sequelize-typescript';
//import bcrypt from 'fastify-bcrypt'

import Roles from './roles';
import userRoles from './userRoles';
@Table({
  timestamps: true,
  paranoid: true  
})

export default class Users extends Model {
  @Column(DataType.VIRTUAL)
  get object() {
    return this.constructor.name.toLowerCase();
  }    


  @Column({field: 'firstName',
    type: DataType.STRING, 
    allowNull: false , 
    validate: {
      notNull: {msg: 'firstName is required'}
    }
  })
  public firstName!: string;


  @Column({field: 'lastName',
    type: DataType.STRING, 
    allowNull: false , 
    validate: {
      notNull: {msg: 'lastName is required'}
    }
  })
  public lastName!: string;

  @Unique({
    name: 'email',
    msg: 'email already taken, Please try a different email'
  })
  @Column({field: 'email',
    type: DataType.STRING, 
    allowNull: false , 
    validate: {
      notNull: {msg: 'email is required'}
    }
  })
  public email!: string;

  @Unique({
    name: 'userName',
    msg: 'username already taken, Please try a different username'
  })
  @Column({field: 'userName',
    type: DataType.STRING, 
    allowNull: false, 
    validate: {
      notNull: {msg: 'userName is required'},      
    }
  })
  public userName!: string;

  @Unique({
    name: 'phone',
    msg: 'phone already taken, Please try a different phone'
  })
  @Column({field: 'phone',
    type: DataType.STRING, 
    allowNull: false , 
    validate: {
      notNull: {msg: 'phone is required'}
    }
  })
  public phone!: string;

  @Column({field: 'dob',
    type: DataType.STRING, 
    allowNull: false , 
    validate: {
      notNull: {msg: 'dob is required'}
    }
  })
  public dob!: string;


  @Column({field: 'password',
    type: DataType.STRING, 
    allowNull: false , 
    
    validate: {
      notNull: {msg: 'password is required'}
    }
  })  
  public password?: string

  @Column({field: 'role_id',
    type: DataType.NUMBER, 
    allowNull: false , 
    
    validate: {
      notNull: {msg: 'role_id is required'}
    }
  })  
  public role_id?: number

  @Column({field: 'role_title',
    type: DataType.STRING, 
    allowNull: false , 
    
    validate: {
      notNull: {msg: 'role_title is required'}
    }
  })  
  public role_title?: string
  
  


  @BelongsToMany(() => Roles, {
    through: {
      model: () => userRoles,
      unique: false,
    },
    foreignKey: 'user_id',
    constraints: false,
  })
  roles: Roles[] | undefined;


  

  static encrypt(password, bcrypt) {  
      
    
    //password = bcrypt.hash(password, 10);
    return bcrypt.hash(password)
  .then(hash => {return hash})
  .catch(err => err.message)
  }

 

  toJSON() {
    return {...super.toJSON(), password: null};
  }
  
}

handler

const role_inserted = await Users.findByPk(id,{include: ["roles"]})

Although I am not facing any blocking errors right now, but this warning keep throwing and I am concerned if this will be a problem as my code base increases to accomodate more complex scenarios.

[App] (sequelize) Warning: Model "Users" is declaring public class fields for attribute(s): "firstName", "lastName", "email", "userName", "phone", "dob", "password", "role_id", "role_title".
[App] These class fields are shadowing Sequelize's attribute getters & setters.
[App] See https://sequelize.org/main/manual/model-basics.html#caveat-with-public-class-fields

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:1
  • Comments:9 (3 by maintainers)

github_iconTop GitHub Comments

5reactions
ephyscommented, Apr 7, 2022

Hey 👋🏼 I’m the one that added this warning, it’s actually thrown by Sequelize itself, it’s not Sequelize-TypeScript

Unless the detection is a false positive, seeing this message typically means you’re going to encounter issues.

Sequelize was designed long before public class fields were a thing, and the way Sequelize handles attributes is incompatible with public class fields. See https://sequelize.org/docs/v6/core-concepts/model-basics/#caveat-with-public-class-fields This is what we’re doing to fix it: https://github.com/sequelize/sequelize/issues/14300

It only works if your TypeScript compiler strips these class fields out during compilation. If you’re using tsc, this can be done by writing your fields like this:

 declare email: string;

instead of this:

 public email!: string;

If you’re using something else, this thread may provide workarounds https://github.com/RobinBuschmann/sequelize-typescript/issues/778

2reactions
MonstraGcommented, Apr 1, 2022

For some reason, this started happening to me after I’ve updated nextjs from “12.1.0” to “12.1.1”.

It also breaks completely, with all properties becoming undefined when attempting to read the model from db.

Enabling\disabling swcMinify doesn’t help.

Read more comments on GitHub >

github_iconTop Results From Across the Web

class fields are shadowing Sequelize's attribute getters & setters
In my code I can use the declare syntax without Babel failing to transpile. However, I can't access the properties so I guess...
Read more >
these class fields are shadowing sequelize's attribute getters
(sequelize) Warning: Model "User" is declaring public class fields for attribute(s): "id", "name", "surname", "email", "image", "emailVerified", "password", " ...
Read more >
How do sequelize getter and setters work? - Stack Overflow
Take for example a user object that has first names and last name fields. You could then create a fullname setter:
Read more >
Getters, Setters & Virtuals - Sequelize
Sequelize allows you to define custom getters and setters for the attributes of your models.
Read more >
Bountysource
class fields are shadowing Sequelize's attribute getters & setters.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found