You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dependabot[bot] e786728d3a
chore(website): bump ssri from 6.0.1 to 6.0.2 in /website (#526)
13 hours ago
.github docs(CONTRIBUTING): add documentation guidelines 2 months ago
.vscode chore: replace "tslint" with "eslint" 2 months ago
docs docs(prop): add "DocumentArray" to array-options example 1 week ago
src feat: use customName and automaticName from buildSchema (#502) 1 month ago
test feat: use customName and automaticName from buildSchema (#502) 1 month ago
website chore(website): bump ssri from 6.0.1 to 6.0.2 in /website (#526) 13 hours ago
.editorconfig enable "strictNullChecks" 11 months ago
.eslintignore chore: replace "tslint" with "eslint" 2 months ago
.eslintrc.js chore: replace "tslint" with "eslint" 2 months ago
.gitignore Add Inheritance Tests 2 years ago
.npmignore Small Changes 2 years ago
.npmrc Set Version to 6.0.0-0 [Pre] 2 years ago
.prettierrc chore: replace "tslint" with "eslint" 2 months ago
.releaserc.js chore: add semantic-release 2 months ago release: v7.6.0 1 month ago
LICENSE Adding FAQ with some faqs 2 years ago docs(README): remove section "install" & "requirements" in favor of quick-start-guide 2 months ago
commitlint.config.js chore: setup git hooks 5 months ago remove "ls" from travis script 9 months ago
husky.config.js chore: setup git hooks 5 months ago
jest.config.json chore(deps): update "ts-jest" to 26.4.4 5 months ago
lint-staged.config.js chore: replace "tslint" with "eslint" 2 months ago
package.json release: v7.6.0 1 month ago Adding build command for tests 2 years ago
tsconfig.json enable "strictNullChecks" 11 months ago
yarn.lock chore: yarn lockfile cleanup 2 months ago


(These badges are from typegoose:master)
Node.js Tests Coverage Status npm

Define Mongoose models using TypeScript classes

Basic usage

import { prop, getModelForClass } from '@typegoose/typegoose';
import * as mongoose from 'mongoose';

class User {
  public name?: string;

  @prop({ type: () => [String] })
  public jobs?: string[];

const UserModel = getModelForClass(User); // UserModel is a regular Mongoose Model with correct types

(async () => {
  await mongoose.connect('mongodb://localhost:27017/', { useNewUrlParser: true, useUnifiedTopology: true, dbName: "test" });

  const { _id: id } = await UserModel.create({ name: 'JohnDoe', jobs: ['Cleaner'] } as User); // an "as" assertion, to have types for all properties
  const user = await UserModel.findById(id).exec();

  console.log(user); // prints { _id: 59218f686409d670a97e53e0, name: 'JohnDoe', __v: 0 }


A common problem when using Mongoose with TypeScript is that you have to define both the Mongoose model and the TypeScript interface. If the model changes, you also have to keep the TypeScript interface file in sync or the TypeScript interface would not represent the real data structure of the model.

Typegoose aims to solve this problem by defining only a TypeScript interface (class), which needs to be enhanced with special Typegoose decorators (like @prop).

Under the hood it uses the Reflect & reflect-metadata API to retrieve the types of the properties, so redundancy can be significantly reduced.

Instead of writing this:

// This is an representation of how typegoose's compile output would look like
interface Car {
  model?: string;

interface Job {
  title?: string;
  position?: string;

interface User {
  name?: string;
  age!: number;
  preferences?: string[];
  mainJob?: Job;
  jobs?: Job[];
  mainCar?: Car | string;
  cars?: (Car | string)[];

const JobSchema = new mongoose.Schema({
  title: String;
  position: String;

const CarModel = mongoose.model('Car', {
  model: string,

const UserModel = mongoose.model('User', {
  name: { type: String },
  age: { type: Number, required: true },
  preferences: [{ type: String }],
  mainJob: { type: JobSchema },
  jobs: [{ type: JobSchema }],
  mainCar: { type: Schema.Types.ObjectId, ref: 'Car' },
  cars: [{ type: Schema.Types.ObjectId, ref: 'Car' }],

You can just write this:

class Job {
  public title?: string;

  public position?: string;

class Car {
  public model?: string;

class User {
  public name?: string;

  @prop({ required: true })
  public age!: number; // This is an single Primitive

  @prop({ type: () => [String] })
  public preferences?: string[]; // This is an Primitive Array

  public mainJob?: Job; // This is an single SubDocument

  @prop({ type: () => Job })
  public jobs?: Job[]; // This is an SubDocument Array

  @prop({ ref: () => Car })
  public mainCar?: Ref<Car>; // This is an single Reference

  @prop({ ref: () => Car })
  public cars?: Ref<Car>[]; // This is an Reference Array

Extra Examples

Requirements & Install

Typegoose's Quick Start Guide


yarn install
yarn run test


This Project should comply with Semver. It uses the Major.Minor.Fix standard (or in NPM terms, Major.Minor.Patch).

Join Our Discord Server

To ask questions or just talk with us, join our Discord Server.


Known Issues

Here are the known-issues


Here is the FAQ


  • Please don't add +1 or similar comments to issues. Use the reactions instead.