1

As per code below inside the "localRegister" function, I added the 'userId' and 'accountType' to the createUserObj object using the bracket notation, so it can satisfy the properties of the User class type.

But I am still getting that message saying that User is missing the userId, accountType properties.

Seems like a simple issue that I just couldn't figure out...how do we make Typescript understand that those properties has been added already, or is there another proper way to add properties?

Thanks in advance.

user.service.ts (partial code)

  async localRegister(createUserDto: LocalUserDto) {
    const passwordHash = await bcrypt.hash(createUserDto.password, 10);
    let createUserObj = { ...createUserDto, password: passwordHash };

    createUserObj['userId'] = uuid();
    createUserObj['accountType'] = 'local';

    this.userCreate(createUserObj);  // <====== typescript error here
       //   Argument of type '{ password: string; username: string; email: string; }' is not assignable to parameter of type 'User'.
       //   Type '{ password: string; username: string; email: string; }' is missing the following properties from type 'User': userId, accountType
  }

  async userCreate(userObj: User) {
    const createdUser = new this.userModel(userObj);
    try {
      await createdUser.save();
    } catch (err) {
      throw new NotFoundException(err.message);
    }
  }

user.schema.ts (where User type is defined)

@Schema()
export class User {
  @Prop({ required: true })
  userId: string;

  @Prop({ required: true })
  username: string;

  @Prop({ unique: true })
  email: string;

  password: string;

  @Prop({ required: true })
  accountType: string;
}

3 Answers 3

1

I'd expect TypeScript to be complaining about indexing into that object with strings. But in any case, if you use brackets notation, I don't think TypeScript broadens the type because you're using strings.

You can build the object with all of the properties from the start:

async localRegister(createUserDto: LocalUserDto) {
    const passwordHash = await bcrypt.hash(createUserDto.password, 10);
    const createUserObj = {
        ...createUserDto,
        password: passwordHash,
        userId: uuid(),                // ***
        accountType: 'local',          // ***
    };

    this.userCreate(createUserObj);
}
Sign up to request clarification or add additional context in comments.

Comments

1

When you add a property "dynamically", like this:

createUserObj['userId'] = uuid();

the typescript compiler cannot really determine the shape of the object. Try this, to let the compiler know exactly what properties are part of the new object:

let createUserObj = { 
    ...createUserDto, 
    password: passwordHash,
    userId: uuid(),
    accountType: 'local'
};

Comments

1

You will have to cast the variable type after properties are added. Typescript won't allow you to change the type of the variable afterwards.

  async localRegister(createUserDto: LocalUserDto) {
    const passwordHash = await bcrypt.hash(createUserDto.password, 10);
    let createUserObj: Partial<User> = { ...createUserDto, password: passwordHash };

    createUserObj.userId = uuid();
    createUserObj.accountType = 'local';

    this.userCreate(createUserObj as User);
  }

Or give it sane defaults

  async localRegister(createUserDto: LocalUserDto) {
    const passwordHash = await bcrypt.hash(createUserDto.password, 10);
    let createUserObj: User = { 
      ...createUserDto,
      password: passwordHash,
      userId: 'invalid uuid',
      accounType: 'local'
    };

    createUserObj.userId = uuid();
    createUserObj.accountType = 'local';

    this.userCreate(createUserObj);
  }

1 Comment

<Pedantry>They aren't casts, they're type assertions.</Pedantry> :-) There's no need for type assertions or fake values in the OP's code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.