'Nodejs + typescript how to use class models?
I am trying to learn how to use class models in nodejs and I will give you an example of what I am trying to achieve.
For example I have user.ts model :
export default class User {
private firstname: string;
private lastname: string;
private email: string;
private password: string;
private isVerified: boolean;
getFirstName() {
return this.firstname;
}
setFirstName(val: string) {
this.firstname = val;
}
getLastName() {
return this.lastname;
}
setLastName(val: string) {
this.lastname = val;
}
getEmail() {
return this.email;
}
setEmail(val: string) {
this.email = val;
}
getPassword() {
return this.password;
}
setPassword(val: string) {
this.password = val;
}
}
And I have auth.ts route :
router.post('/login', async (req: Request, res: Response) => {
const { error } = loginValidation(req.body);
if (error) return res.status(400).send(error.details);
const user = await UserModel.findOne({ email: req.body.email });
if (!user) return res.status(400).send('Email doesn`t exist');
if (!user.isVerified) return res.status(400).send('User is not verified, check Your email first');
const validPass = await bcrypt.compare(req.body.password, user.password);
if(!validPass) return res.status(400).send('Invalid password');
const userResponse = new UserModel({
firstname: user.firstname,
lastname: user.lastname,
email: user.email,
createdAt: user.createdAt,
updatedAt: user.updatedAt,
isVerified: req.body.isVerified
});
try {
const token = jwt.sign({_id: user._id}, process.env.TOKEN_SECRET,{ expiresIn: '8h' });
res.header('auth-token', token);
res.send(userResponse);
} catch (err) {
res.status(400).send(err);
}
}
I want to use my user.model for req.body, but don't know how :
Tryed :
const user: User = req.body;
user.getFirstname() - getFirstname() is not a function
user.setFirstname(req.body.firstname) <- setFirstname is not a function()
How can I attach req.body to user model ?
Solution 1:[1]
req.body
returns a JSON object with an unknown type. You need a type guard to check and be sure req.body
contains the value you need. You can learn more about it here https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types.
But firstly, you're trying to achieve getters and setters in typescript but doing it the wrong way.
So i re-wrote your User model class
export default class User {
private _firstname: string;
private _lastname: string;
private _email: string;
private _password: string;
private _isVerified: boolean;
get firstname() {
return this._firstname;
}
set firstname(val: string) {
this._firstname = val;
}
get lastname() {
return this._lastname;
}
set lastname(val: string) {
this._lastname = val;
}
get email() {
return this._email;
}
set email(val: string) {
this._email = val;
}
get password() {
return this._password;
}
set password(val: string) {
this._password = val;
}
}
and your auth.ts route
router.post('/login', async (req: Request, res: Response) => {
if((req.body as User).firstname){
const user: User = req.body as User
...
}
}
and you can set firstname through getter and setter by
user.firstname // get first name
user.firstname = 'your name'
Solution 2:[2]
Why not use a constructor to model the data you receive on the request? This also works on the client-side and is useful to assure you have an object of a certain type.
What I normally do is
export default class User {
private firstname: string;
private lastname: string;
private email: string;
private password: string;
private isVerified: boolean;
constructor(data: Partial<User>){ // Partial<User> helps type the data
// I'm using null or false as default value but you can change it
this.firstname = userData.firstname || null
this.lastname = userData.lastname || null
this.email = userData.email || null
this.password = userData.password || null
this.isVerified = userData.isVerified || false
}
// ... getters, setters and other methods
}
So whenever you want to model data you got from any source you may do
const user = new User(req.body)
// And now you are able to i.g.
const email = user.getEmail()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | cigien |