title: How do you fill mongoose entities with values based on an interface?
body: <p>I'm working on a NestJS API and I'm trying to create some documents with mongoose, but i'm running into some problems. I was following the <a href="https://docs.nestjs.com/techniques/mongodb" rel="nofollow noreferrer">NestJS Mongo Docs</a> and an <a href="https://auth0.com/blog/modern-full-stack-development-with-nestjs-react-typescript-and-mongodb-part-1/" rel="nofollow noreferrer">Auth0 API Guide</a> to get a good grip of what you are supposed to do.</p>
  <blockquote>
  <p>[NOTE] I removed all obvious and out-of-scope imports on the code blocks. I also registered the models als they should be, so that's nothing to question either. It is also <strong>necessary</strong> that I can fill the values in myself, since in the real world product I have to do calculations to fill in the values. That's why I decided to fill in the values first, instead of just passing the DTO to the mongoose entity.</p>
  </blockquote>
  <p>This is my mongoose document entity:</p>
  <pre class="lang-js prettyprint-override"><code>// src/user/interfaces/user.interface.ts
  import { Document } from 'mongoose';
  
  export interface User extends Document {
     readonly string firstName;
     readonly string lastName;
     readonly string fullName;
  }
  </code></pre>
  <p>But.. when I try to fill the values in the service like this:</p>
  <pre class="lang-js prettyprint-override"><code>// src/user/user.service.ts
  import { User } from './interfaces/user.interface';
  
  @Injectable();
  export class UserService {
    constructor(
      @InjectModel(&quot;User&quot;)
      private readonly userModel: Model&lt;User&gt;,
    ) {}
  
    async createUser(dto: CreateUserDTO): Promise&lt;User&gt; {
      const user: User = {
         firstName: dto.firstName,
         lastName: dto.lastName,
         fullName: `${dto.firstName} ${dto.lastName}`,
      }
      return await this.userModel.create(user);
    }
  }
  </code></pre>
  <p>It results in the following error and won't compile:</p>
  <pre><code>Type '{ firstName: string; lastName: string; fullName: string; }'
    is missing the following properties from type 'User': increment, model, $isDeleted, remove, and 52 more.ts(2740)
  </code></pre>
  <p>These, of course are errors since it extends the Mongoose Document and those values aren't filled.</p>
  <hr />
  <p>I have tried the following already but I wasn't pleased with the &quot;solutions&quot;</p>
  <h2><strong>Attempt 1</strong></h2>
  <p><em>Pass it directly as an argument, unfortunately this does not give me the autocomplete and validation</em></p>
  <pre class="lang-js prettyprint-override"><code>async createUser(dto: CreateUserDTO): Promise&lt;User&gt; {
    const newUser = new this.userModel({
      firstName: dto.firstName,
      lastName: dto.lastName,
      fullName: `${dto.firstName} ${dto.lastName}`,
    });
    return await newUser.save();
  }
  </code></pre>
  <hr />
  <h2><strong>Attempt 2</strong></h2>
  <p><em>Make second interface and use interface A in the filling, and interface B in the returning and calling</em></p>
  <pre class="lang-js prettyprint-override"><code>// src/user/interfaces/user.interface.ts
  import { Document } from 'mongoose';
  
  export interface User {
     readonly string firstName;
     readonly string lastName;
     readonly string fullName;
  }
  
  export interface UserDoc extends User, Document {}
  </code></pre>
  <p>and then use it in the service like:</p>
  <pre class="lang-js prettyprint-override"><code>// src/user/user.service.ts
  import { User, UserDoc } from './interfaces/user.interface';
  
  @Injectable();
  export class UserService {
    constructor(
      @InjectModel(&quot;User&quot;)
      private readonly userModel: Model&lt;UserDoc&gt;,
    ) {}
  
    async createUser(dto: CreateUserDTO): Promise&lt;UserDoc&gt; {
      const user: User = {
         firstName: dto.firstName,
         lastName: dto.lastName,
         fullName: `${dto.firstName} ${dto.lastName}`,
      }
      return await this.userModel.create(user);
    }
  }
  </code></pre>
  <p>Now, this works, but it's really ugly and you also have to make sure you are using the right interface at the right time, so quite inconvenient.</p>
  <hr />
  <p><strong>TL;DR; Is there a way to have a strongly-typed mongoose entities, in which you can put the values which will get autocompleted like in <code>Attempt B</code> but better and cleaner?</strong></p>