The operand of a 'delete' Operator must be optional

Asked

Viewed 6,191 times

8

I’m having trouble understanding why it is not possible to apply delete user.password in the code below

Terminal return:

The operand of a 'delete' Operator must be optional.

My code:

import { Request, Response } from 'express';
import { getRepository } from 'typeorm';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';

import User from '../models/User';

class AuthController {
  async authenticate(req: Request, res: Response){
    const repository = getRepository(User);

    const { email, password } = req.body;

    const user = await repository.findOne({
      where: { email }
    });

    if(!user) {
      return res.sendStatus(401);
    }

    const isValidPassword = await bcrypt.compare(password, user.password);

    if(!isValidPassword) {
      return res.sendStatus(401);
    }
        
    const token = jwt.sign({ id: user.id}, 'secret', { expiresIn: '1d'});
 
    delete user.password;
 
    return res.json({
      user,
      token,
    });
  }
}

export default new AuthController();

3 answers

13


This error was introduced in version 4.0, and is one of the Breaking changes:

When using the delete Operator in strictNullChecks, the operand must now be any, unknown, never, or be optional (in that it contains undefined in the type). Otherwise, use of the delete Operator is an error.

That is, Typescript will warn about the use of delete on a property that is not optional, since this would be breaking the interface contract.

Solving the mistake

To avoid this problem, make the password an optional property or create a new interface for it. For example:

interface User {
    name: string;
    password: string;
}

const user: User = { name: 'Rafael', password: '123' };
delete user.password;
// Acima não permite a remoção porque tornaria a tipagem inconsistente, quebrando o contrato da interface


interface User2 {
    name: string;
    password?: string;
}

const user2: User2 = { name: 'Rafael', password: '123' };
delete user2.password;
// Como `password` pode ser `undefined`, o TypeScript não reporta erro algum

See the example on Playground.


Ignoring the error (unsaved)

There is an alternative that I will put here just to leave registered, but it is good to avoid it because it does not solve the problem, just makes Typescript "stop complaining":

// @ts-expect-error Aqui vai ocorrer um erro, mas estou ignorando
delete user.password;

See on Playground.

This is not a good alternative because if you are going to use the variable user later, Typescript will not point out that the password can be undefined. That is, the interface contract has been broken and nobody knows it, can cause problems in the future.

It is better to think of a way to have everything consistent even if it is a little more verbose, after all, if it has been decided to use typescripts, strive to use them right.

1

Another solution would be to complete your standard MVC - Models, Views, Controllers. This way you can standardize the answer you want to return without this type of gross change.

That is ... create a folder views with the file userViews.ts with the following code:

import User from '../models/User';

export default {
  render(user: User){
    return {
      id: user.id,
      email: user.email,
      // aqui vc poderá acrescentar futuramente novos campos que serão retornados
    };
  }
}

After creating the View, change the return of your authentication to:

 return res.json({
  user: usersView.render(user),
  token,
});

I hope I’ve helped.

  • 1

    Also don’t forget to import your View from users in your authentication controller of course. import usersView from '.. /views/Usersviews';

0

There is a simpler path than modifying the code. (because it is basic the mandatory password)

In your tsconfig.json file search for 'strictNullChecks', remove the comment from that option and leave it as false. thus:

"strictNullChecks": false,              /* Enable strict null checks. */

Save your file and go back to code! ;)

if you have cleaned your file, just add this line!

I hope I’ve helped.

  • 4

    Most of the time, in a project that has already started with the strictNullChecks activated, this, at least in my opinion, would cause more harm than good, because it would make some codes more susceptible to error linked to null and undefined, who were once being warned by flag in question. The subject of the question is even a bug predicted by flag. Anyway, if it is to "cheat", disabling the option, the security that Typescript brings, nor worth using it...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.