How to type MongoDB collections with typescript
Jun 5, 2025There are several ways to type your MongoDB collections when using typescript, you can cast it to the desired type or use generics:
import type { Db, ObjectId } from "mongodb";
interface IPost {
_id: ObjectId;
title: string;
date: Date;
author: ObjectId;
}
async function getPosts(db: Db) {
const posts = await db.collection<IPost>("posts").find().toArray();
// or const posts = await db.collection("posts").find().toArray() as IPost[];
return posts;
}
While this works, it quickly becomes hard to maintain when you need to access the same collection several times across the codebase in multiple files, and keeping track of which type belong to which collection can be daunting.
async function getPosts(db: Db) {
return db.collection<IPost>("posts").find().toArray();
}
// in another file
async function getPostsByAuthor(db: Db, authorId: ObjectId) {
const posts = await db
.collection<IPost>("posts")
.find({ author: authorId })
.toArray();
return posts;
}
Luckily there's a better way to define which types belong to a collection in a single source of truth and have the correct type everywhere you need to access the collection.
This can be accomplished by leveraging typescript declaration merging and some clever use of generics:
// types.ts
import type { ObjectId } from "mongodb";
export interface IPost {
_id: ObjectId;
title: string;
date: Date;
}
// mongodb-collections.d.ts
import type { IPost } from "./types";
interface Collections {
posts: IPost;
// Add the rest of your collections here in the format
// <collection-name>: CollectionType
}
declare module "mongodb" {
interface Db {
collection<K extends keyof Collections>(
collection: K,
collectionOptions?: CollectionOptions,
): Collection<Collections[K]>;
}
}
Now you can use MongoDB and the types will be automatically inferred for the collection:
// main.ts
import type { Db } from "mongodb";
async function getPosts(db: Db) {
// no need to specify IPost type here, it is inferred from "posts" collection
const posts = await db.collection("posts").find().toArray();
// post is IPost[]
return posts;
}
async function getPostsByAuthor(db: Db, authorId: ObjectId) {
const posts = await db
.collection("posts")
.find({ author: authorId })
.toArray();
// post is IPost[]
return posts;
}
That's it! enjoy having correct types in the whole codebase.
See a working example on GitHub