question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How do you get type checking for schema definitions to work when using Model.create or other Model methods?

See original GitHub issue

Do you want to request a feature or report a bug?

I have a question.

What is the current behavior?

Hello. I have been using Mongoose for years, and recently I started with Typescript so currently in the process of converting, and I have a couple of quick questions. Let’s say I have a very simple schema, nearly identical as the one provided in the TypeScript Support section of Mongoose docs.

import { model, Schema } from 'mongoose';

interface IUser {
    name: string;
    age: number;
}

const UserSchema = new Schema<IUser>({
    name: { type: String, required: true },
    age: { type: Number, required: true },
});

const User = model<IUser>('User', UserSchema);

What is the expected behavior?

What I want to be able to have is a type checking against the schema definition, whenever I use methods such as Model.create or when I create a new instance of the User model. Here for example, I expect Typescript to complain (but it doesn’t):

const createUser = async () => {
    const user = new User({ foo: 'bar' });
    await User.create({ foo: 'bar' });

    // or even

    const user2 = new User({ name: false, age: 'invalid' });
};

In this example, it lets me use completely arbitrary object properties, while also letting me omit name and age keys as defined in by IUser interface in UserSchema and User model. As far as Typescript is concerned, all of this code is valid and no errors are detected. I can slightly improve this if I force the IUser interface when creating the document, however, as you can see this only solves half of the problem.

const createUser = async () => {
    await User.create(<IUser>{ foo: 'bar' });       // works as intended, problem is detected (wavy red line)

    await User.create(<IUser>{});                   // not working, empty object
    await User.create(<IUser>{ name: 'bar' });      // not working, "age" property is missing
    await User.create(<IUser>{ age: 30 });          // not working, "name" property is missing
};

image

In VSCode, if I hover with my mouse over Schema where I am defining it, it lets me see how the definition works, and that tells me that all the object properties are set as optional and not respecting the IUser interface where in fact they are required:

image

But my knowledge in TypeScript is not good enough to understand why this is happening or if it’s necessary.

Surprisingly, I was able to find very little on this topic online, closest one is this question on StackOverflow from 2 months ago, but it has no answers.

So overall my question is, how do I achieve type checking using model methods, is it even possible, and if it is, what is the correct way to do it? I apologize in advance in case I am missing something obvious here, as I mentioned was only starting with TS and TS Mongoose so there is a possibility that I am doing something incorrectly. Nevertheless, any guidance or quick example would be highly appreciated. Cheers!

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that “latest” is not a version.

Node.js 16.13.1 Mongoose 6.1.3 VSCode 1.63.2 tsconfig.json

{
    "compilerOptions": {
        "target": "ES2020",
        "module": "commonjs",
        "rootDir": "./src",
        "outDir": "./out",
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "preserveWatchOutput": true,
        "esModuleInterop": true,
        /* ESBuild specific config */
        "noEmit": true,
        "watch": true
    },
    "exclude": [
        "**/node_modules",
        "**/.*/",
        "src/assets/**",
    ],
    "include": [
        "src"
    ]
}

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:7

github_iconTop GitHub Comments

4reactions
vkarpov15commented, Jan 5, 2022

It’s very strange that intellisense doesn’t pick up that User.create<IUser>() takes IUser as a param. If that’s the case, I’m not sure what else we can do to support intellisense.

Re new User<IUser>({...}), we don’t currently support that, but I just added that and we’ll release that in v6.1.6

0reactions
hmeerlocommented, Jun 29, 2022

@vkarpov15 What is the reasoning behind this? When would I ever want to perform an update with properties that are not in the schema? Isn’t this exactly why we would want TypeScript in the first place?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Methods for TypeScript runtime type checking - LogRocket Blog
Explore five methods of performing TypeScript type checks at runtime in this post and learn each of their advantages and disadvantages.
Read more >
Mongoose v6.8.2: Schemas
Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound ......
Read more >
Model instance reference - Django documentation
Creating objects​​ To create a new instance of a model, instantiate it like any other Python class: class Model (**kwargs) The keyword arguments...
Read more >
Typescript mongoose static model method "Property does not ...
Create a Schema corresponding to the document interface. const schema = new Schema<User>({ name: { type: String ...
Read more >
Working with models and mapping templates - Amazon API ...
The payload can have a data model according to the JSON schema draft 4 . You must define the model in order to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found