Skip to content

Conversation

@Catwallon
Copy link

@Catwallon Catwallon commented Oct 15, 2025

Summary

This pull request changes the default generic type T for the Document class from unknown to ObjectId.

The motivation for this change is to improve the developer experience for TypeScript users by providing a more practical and intuitive default. In the vast majority of Mongoose schemas, the _id field is an ObjectId by default. Aligning the generic type T (which represents the type of _id) with this behavior reduces boilerplate and prevents potential type errors.

Currently, developers often have to explicitly define Document<ObjectId> to get proper type-safety on the _id field. By making ObjectId the default, the types will work out-of-the-box for the most common use case.

This also raises a question: I'm curious about the original rationale for choosing unknown as the default. There may be a design consideration I am not aware of, and understanding it would be valuable.

Examples

This change directly impacts type inference on document instances.

Current Behavior

With the default T = unknown, accessing methods on _id without explicit typing results in a TypeScript error.

import { Document, Schema, model } from 'mongoose';

// Interface extending `Document` uses the default generic `unknown` for the `_id`.
interface IUser extends Document {
  name: string;
}

const userSchema = new Schema<IUser>({ name: { type: String, required: true } });
const User = model<IUser>('User', userSchema);

const user = new User({ name: 'Jane Doe' });

// `user._id` is typed as `unknown`.
// The following line causes a TypeScript error:
// >> Property 'toString' does not exist on type 'unknown'.
const idString = user._id.toString();

After this PR

With the default T = ObjectId, the _id property is correctly typed, and no errors occur.

import { Document, Schema, model } from 'mongoose';

// Interface extending `Document` now uses the new default generic `ObjectId` for the `_id`.
interface IUser extends Document {
  name: string;
}

const userSchema = new Schema<IUser>({ name: { type: String, required: true } });
const User = model<IUser>('User', userSchema);

const user = new User({ name: 'Jane Doe' });

// `user._id` is correctly typed as `ObjectId`.
// This code now works perfectly without any type errors.
const idString = user._id.toString(); // OK!

@Catwallon Catwallon force-pushed the fix/default_id_type branch from 122d283 to cb45fbf Compare October 16, 2025 08:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant