Node + Mongoose + TypeScript: Defining Schemas and Models
( 64 Articles)

This article walks you through a concise and straight-to-the-point example of declaring schemas and defining models with Mongoose and TypeScript. Without any further ado (e.g, talking about the history of Node.js or explaining what MongoDB is or why you should use Mongoose), let’s get our hands dirty and write some code.
Overview
We will work with a database that is used for a blog. It simply contains 2 collections:
- users: stores users’ information
- posts: stores blog posts. Each post references a certain user. A single user can own multiple posts.
In general, when using Mongoose with TypeScript, we will follow the steps below:
- Declare interfaces representing documents
- Define schemas corresponding to the document interfaces
- Create models
The Code
User Model
Create a file named user.model.ts (the name is totally up to you) and add the following:
// user.model.ts
import { Document, Schema, model } from 'mongoose';
// Create the interface
export interface IUser extends Document {
firstName: string;
lastName: string;
email: string;
password: string;
photo?: string;
birthday?: Date;
}
// Create the schema
const UserSchema = new Schema<IUser>({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
photo: String,
birthday: String
}, {
timestamps: {
createdAt: 'createdAt',
updatedAt: "updatedAt"
}
});
// Create and export user model
export const UserModel = model<IUser>("User", UserSchema);
Post Model
Create a new file named post.model.ts in the same directory where user.model.ts resides. We will reference each post with a specific _id of a user. The correct type for the user ref field is mongoose.Schema.Types.ObjectId (the type for user when defining the post interface should be Types.ObjectId).
import { Document, Schema, Types, model } from 'mongoose';
// post interface
export interface IPost extends Document {
title: string;
content: string;
thumbnail?: string;
status: "draft" | "published" | "trashed";
views: number;
user: Types.ObjectId;
}
// post schema
const PostSchema = new Schema<IPost>({
title: {
type: String,
required: true
},
content: {
type: String,
required: true
},
thumbnail: String,
status: {
type: String,
enum: ["draft", "published", "trashed"],
default: "draft"
},
views: {
type: Number,
default: 0
},
user: {
type: Schema.Types.ObjectId,
ref: "User",
required: true,
}
}, {
timestamps: {
createdAt: 'createdAt',
updatedAt: "updatedAt"
}
})
// create and export post model
export const PostModel = model<IPost>("Post", PostSchema);
Afterword
You’ve learned the fundamentals of using Node.js with TypeScript and Mongoose. From now on, you can extend the example above and make it a more complex thing. Change some lines of code and see what happens.
If you’d like to explore more new and exciting stuff about modern Node.js, take a look at the following articles:
- Best open-source ORM and ODM libraries for Node.js
- 7 Best Open-Source HTTP Request Libraries for Node.js
- Node.js: How to Use “Import” and “Require” in the Same File
- Using Axios to download images and videos in Node.js
- Node.js: Get File Name and Extension from Path/URL
- How to Generate Slugs from Titles in Node.js
You can also check out our Node.js category page for the latest tutorials and examples.