Skip to content

Instance Methods and Properties returned from Query are undefined #13339

@jgudo

Description

@jgudo

What you are doing?

I am querying for a user using findOne method but the methods and properties of the returned instance are undefined. To be honest, it applies to all type of query that I perform.

I am using Sequelize with TypeScript in defining my model.

interface IUserAuthAttributes {
  user_auth_id: number;
  username: string;
  password: string;
  full_name: string;
  disable_user: number;
  user_level_id: number;
  created_modified: string | Date;
}

interface IUserAuthCreationAttributes
  extends Optional<IUserAuthAttributes, 'user_auth_id'> { }

export class UserAuth
  extends Model<IUserAuthAttributes, IUserAuthCreationAttributes>
  implements IUserAuthAttributes {
  public user_auth_id!: number;
  public username!: string;
  public password!: string;
  public full_name!: string;
  public disable_user: number;
  public user_level_id!: number;
  public created_modified: string | Date;

  public getRole: () => 'meter_reader' | 'evaluator' | null;
}

UserAuth.init({
  user_auth_id: {
    autoIncrement: true,
    type: DataTypes.INTEGER.UNSIGNED,
    allowNull: true,
    primaryKey: true
  },
  username: {
    type: DataTypes.STRING(20),
    allowNull: false,
    defaultValue: ""
  },
  password: {
    type: DataTypes.STRING(100),
    allowNull: false,
    defaultValue: ""
  },
  full_name: {
    type: DataTypes.STRING(100),
    allowNull: false,
    defaultValue: ""
  },
  disable_user: {
    type: DataTypes.TINYINT,
    allowNull: false,
    defaultValue: 0
  },
  user_level_id: {
    type: DataTypes.TINYINT,
    allowNull: false,
    defaultValue: 18
  },
  created_modified: {
    type: DataTypes.DATE,
    allowNull: false,
    defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
  }
},
  {
    sequelize: DBInstance,
    tableName: 'user_auth',
    timestamps: false
  }
);

UserAuth.prototype.getRole = function () {
  let role = null;

  if (this.user_level_id === 13) {
    role = 'meter_reader';
  } else if (this.user_level_id === 9) {
    role = 'evaluator';
  }

  return role;
}

What do you expect to happen?

I expect the returned user to be able to execute the getRole instance method and return expected result but fails to execute it and says that TypeError: foundUser.getRole is not a function. Trying to access to other properties like username also fails and I still have to use the getDataValue method like getDataValue('username') to access the username property. I could also use the get method const user = foundUser.get({ plain: true }) or add the { raw: true } on my query to have access on the properties but not on the instance method.

What is actually happening?

This is the code that I'm trying to run.

async login(req: Request, res: Response, next: NextFunction) {
        try {
            const { username, password } = req.body;

            // Check if username exists
            const foundUser = await UserAuth.findOne({
                where: {
                    [Op.or]: [
                        { user_level_id: 9 },
                        { user_level_id: 13 },
                    ],
                    username: username,
                    disable_user: 0
                },
                attributes: {
                    include: ['user_auth_id', 'username', 'password', 'disable_user']
                },
            });

            if (!foundUser) {
                return next(new ErrorHandler(401, 'Incorrect credentials.'));
            }

            console.log(foundUser.getRole()); // TypeError: foundUser.getRole is not a function

            res.status(200).json(foundUser);
        } catch (err) {
            next(err);
        }
    }

While inspecting the returned user from the query, using console.log(foundUser), this is what it returns.

UserAuth {
  dataValues: {
    user_auth_id: 11,
    username: 'dhel',
    password: '$2a$10$AgiooENdIcVvwK.KQCmAgecT04qgcYbTvzqJ/j0wW/MxvBBVTdV1m',
    full_name: 'ADELFA BALATBAT',
    disable_user: 0,
    user_level_id: 9,
    created_modified: 2021-06-21T11:37:29.000Z
  },
  _previousDataValues: {
    user_auth_id: 11,
    username: 'dhel',
    password: '$2a$10$AgiooENdIcVvwK.KQCmAgecT04qgcYbTvzqJ/j0wW/MxvBBVTdV1m',
    full_name: 'ADELFA BALATBAT',
    disable_user: 0,
    user_level_id: 9,
    created_modified: 2021-06-21T11:37:29.000Z
  },
  _changed: Set(0) {},
  _options: {
    isNewRecord: false,
    _schema: null,
    _schemaDelimiter: '',
    raw: true,
    attributes: [
      'user_auth_id',
      'username',
      'password',
      'full_name',
      'disable_user',
      'user_level_id',
      'created_modified',
      'user_auth_id',
      'username',
      'password',
      'disable_user'
    ]
  },
  isNewRecord: false,
  user_auth_id: undefined,
  username: undefined,
  password: undefined,
  full_name: undefined,
  disable_user: undefined,
  user_level_id: undefined,
  created_modified: undefined,
  toUserJSON: undefined,
  getRole: undefined
}

As you can see from the returned User from above, the instance methods getRole is undefined as well as properties outside dataValues.

Which dialect you are using ?

I am using mysql

Which sequelize version you are using?

I am using using sequlize: 6.6.2 mysql2: 2.2.5 typescript:.4.2.4

More info

I am using ts-node: 9.1.1 , tsconfig-paths:3.9.0 in order to compile and resolve path aliases on my typescript code.
and start my server with this script "start": "nodemon --exec ts-node --files -r tsconfig-paths/register src/index.ts"

My tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "lib": [ "esnext", "esnext.asynciterable" ],
    "baseUrl": ".",
    "paths": { 
        "@/*": [  "./src/*" ]  
    },
    "typeRoots": [ "./node_modules/@types",  "./src/types" ],
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node",
    "module": "commonjs",
    "pretty": true,
    "sourceMap": true,
    "outDir": "./build",
    "allowJs": true,
    "noEmit": false,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "resolveJsonModule": true
  },
  "include": [  "./src/**/*",  ".sequelizerc", ".env"  ],
  "exclude": [ "node_modules" ],
}

It would be really helpful if you can give me an insight as to why this is happening.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions