What is the effective way to input automatically generated Mongo fields in typescript?

Following the guidelines from the official documentation for implementing mongoose v5.13.x with TypeScript, I have developed my model as shown below:


import mongoose, { Model, Schema, Types } from "mongoose";

export interface Foo {
  label: string;
  archived: boolean;
  created_at: number;
  updated_at: number;
}

const FooSchema = new Schema<Foo, Model<Foo>, Foo>(
  {
    label: { type: String },
    archived: { type: Boolean, default: false },
  },
  {
    timestamps: {
      createdAt: "created_at",
      updatedAt: "updated_at",
      currentTime: () => Date.now() / 1000,
    },
  }
);

const Foo: Model<Foo> = mongoose.model<Foo>("Foo", FooSchema);

Now, my goal is to implement functions that can create and retrieve instances of this model. When creating a new instance, certain fields like _id, archived, created_at, and updated_at should be optional. However, when retrieving an existing instance, all these fields should be accessible. Here's an example:


type FooInput = {
  label: string;
};

type FooOutput = {
  _id: string;
  label: string;
  archived: boolean;
  created_at: number;
  updated_at: number;
};

export const createFoo = async (foo: FooInput): Promise<FooOutput> => {
  return await Foo.create(foo);
};

Unfortunately, I am encountering type errors while trying to implement this approach; the output of Foo.create() claims that _id is optional, leading to conflicts when specifying types. How can I correctly define the fields such as _id, created_at, etc in this scenario?

Answer №1

Extending your types with mongoose.Document is a possibility

Answer №2

It appears that using Model.create() can be quite type-unsafe, requiring manual declaration with a custom FooInput type to handle default values.

To address this issue, I decided to create a specialized TypesafeModel, which includes customized create and update methods to improve typing accuracy.

import mongoose, { Model, Schema, Types, EnforceDocument, FilterQuery } from "mongoose";

interface TypesafeModel<D, I = Partial<D>, QueryHelpers = {}, Methods = {}> extends Omit<Model<D, QueryHelpers, Methods>, 'create' | 'update'> {
  create(doc: I): Promise<EnforceDocument<D, Methods>>,
  update(filter: FilterQuery<D>, doc: Partial<I>): Promise<EnforceDocument<D, Methods>>,
}

export type Foo = {
  _id: Types.ObjectId,
  label: string;
  extra?: string;

  archived: boolean;
  created_at: number;
  updated_at: number;
}

type FooFieldsWithDefaults = '_id' | 'archived' | 'created_at' | 'updated_at'
type FooInput = Omit<Foo, FooFieldsWithDefaults>


interface FooQueryHelpers {}
interface FooMethods {}

interface FooModel extends TypesafeModel<Foo, FooInput, FooQueryHelpers, FooMethods> {
  // statics go here
}

const FooSchema = new Schema<Foo, FooModel, Foo>(
  {
    label: { type: String, required: true },
    extra: { type: String },

    archived: { type: Boolean, default: false },
  },
  {
    timestamps: {
      createdAt: "created_at",
      updatedAt: "updated_at",
      currentTime: () => Date.now() / 1000,
    },
  }
);

const Foo = mongoose.model<Foo, FooModel>("Foo", FooSchema);

export const createFoo = async (foo: FooInput): Promise<Foo> => {
  const good = await Foo.create(foo); 
  const bad = await Foo.create({ wrong: 'stuff' }); // hooray, a type error!
  const bad2 = await Foo.update({'_id': '123'}, { wrong: 'stuff'}); // hooray, a type error!

  return good
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Implementing automatic page reloaded with Node.js and express-handlebars

I'm currently working on a Node.js and Express project that utilizes express-handlebars as the app's template engine. The application reads data from a MySQL database and presents it in a table format. To enable pagination, I've implemented ...

Ensuring the structure of a model in a JSON array with Angular

While working with Angular, I have a model defined as follows: export interface MyModel { id: number; content: string; } In one of my services, I fetch JSON data that matches the attributes of MyModel. Here's an example: function getMyModel ...

Mistakes in Compiling Typescript Code in Angular 2

Currently, I am utilizing Visual Studio 2017 for the development of an Angular 2 application with an Asp.Net Core WebApi backend. My guide through this process is the ASP.NET Core and Angular 2 Book authored by Valerio De Sanctis. Initially, everything was ...

Exploring ExpressJS: When to choose app.use for serving static files over app.get()

I'm struggling to make my console.log statement appear within the app.get() route when using Express to serve files. Currently, I am utilizing app.use(express.static("public")); to serve from the public folder. Below is the complete code snippet: // ...

Tips for performing a custom atomic update on a mongodb document

While MongoDB does offer the ability to perform atomic updates using findOneAndUpdate, it is limited to basic operations such as set or increment. What I really need is a way to apply a custom function to transform my document: const updateDoc = async (e ...

Executing a transaction in Node and MongoDB to update data and returning a response upon completion

Using a combination of Node.js and MongoDB, I am able to successfully update transactions from my React app. Once the updates are completed, I need to receive a response indicating whether the operation was a success or if there was an error. In my curren ...

Count the occurrences of different fields in a document based on a specified condition

Seeking a way to extract specific values and calculate the frequency of those values in a collection based on a certain key's ID. Consider this example of a single document from a Game Logs collection: { "_id": "5af88940b73b2936dcb6dfdb", "da ...

Vue: rendering props cannot be utilized with TSX

After switching my setup from JSX in a Vue component to TS with vue-class-component, I found that only the code snippet below works for me (as shown in the example on repo): import Vue from 'vue' import { Component } from 'vue-property-dec ...

Changing the color of a Chart.js chart in Angular: A step-by-step guide

I've been struggling to change the color of my chart without success. Any assistance on this matter would be greatly appreciated. Despite trying to assign color values to datasets, I am still unable to achieve the desired result. This is a snippet f ...

Is the indigo-pink color scheme fully implemented after installing @angular/material and scss using ng add command?

After running ng add @angular/material, we are prompted to choose a CSS framework and theme. I opted for indigo-pink and scss. Will the material components automatically inherit this theme, or do we need to take additional steps? When using normal CSS (wi ...

Is 'get Some(): Todo[] {}' some sort of abbreviated method?

While going through an Angular services tutorial, I stumbled upon some code snippet. fetchData(): Data[] { return [ { label: "Data 1", type: DataType.INTEGER }, { label: "Data 2", type: DataType.STRING }, { label: "Data 3", type: DataType.BO ...

Converting text data into JSON format using JavaScript

When working with my application, I am loading text data from a text file: The contents of this txt file are as follows: console.log(myData): ### Comment 1 ## Comment two dataone=1 datatwo=2 ## Comment N dataThree=3 I am looking to convert this data to ...

The 'propTypes' property is not found on the 'typeof TextInput' type declaration

Trying my hand at creating a react-native component using Typescript for the first time, but I ran into an issue on line 51: Property 'propTypes' does not exist on type 'typeof TextInput Couldn't find any helpful information on similar ...

An approach to mocking the 'global' property in Styled JSX when testing with Jest

Encountering an error while trying to run tests on a NextJS project. The error message reads: TypeError: _css.default.global is not a function To mock StyledJSX, I added a __mocks__/styled-jsx/css.js file with the following content: const css = () => { ...

Creating a seamless REST API using Node.js and the Tedious library: A comprehensive guide

I am facing an issue with retrieving SQL data in my Express API. The page is continuously loading and showing a blank screen, however I can see the SQL data response in the console. Here is my index.js code : var Connection = require("tedious"). ...

Trouble encountered while iterating over an array in Typescript from an antd form

I'm currently working on a React + TS webpage with the ant design library, and I've encountered an issue with types in my form component. I have created an array to iterate through them and display the form. Link to CodeSandbox One of the eleme ...

What is the location for adjusting the angular strictness flags that determine the level of strictness for strictTemplates?

Currently in the process of transitioning our application to strictTemplates, we are encountering a multitude of errors, some more significant than others. As a result, I decided to adjust the strictness of the angular type checker and came across these s ...

Prisma and Next.js: Changes to content require re-deployment for updates to take effect

Just recently, I launched a new website on Vercel. My web application is being built with Prisma and Next.js. However, I'm currently facing an issue where the content doesn't update in real-time unless I manually re-deploy the application. Here&a ...

Struggling with TypeScript generics and mapping record types is becoming quite a headache

What is the Purpose of my Code? I have a set of functions stored in an object like this: const actions = { foo: (state: string, action: {payload: string}) => {}, bar: (state: string, action: {payload: number}) => {}, baz: (state: string, ...

Is there a way to simultaneously filter by two attributes using mat-select-filter in Angular?

I have integrated the mat-select-filter library in my Angular project, but I am facing an issue with the displayMember filter. Currently, it only filters by code, but I would like it to also filter by name simultaneously. Is there a way to achieve this u ...