Derive TypeScript Types from Mongoose Schemas
When working with Mongoose and TypeScript, two helper types make your life much easier: /** * Extracts the “plain” shape of your schema— * just the fields you defined, without Mongoose’s built-in methods or `_id`. */ export type User = InferSchemaType; /** * Represents a fully “hydrated” Mongoose document: * your fields plus all of Mongoose’s methods and metadata * (e.g. `_id`, `save()`, `populate()`, etc.). */ export type UserDocument = HydratedDocument; export const userModel = model("user", userSchema); InferSchemaType • Produces a pure TypeScript type from your schema definition. • Use it whenever you need just the data shape (e.g. DTOs, service inputs/outputs). HydratedDocument • Wraps your base type T with Mongoose’s document helpers. • Use it for any function that deals with real, database-backed documents (e.g. returns from find, create, save). For example, in a repository interface you might write: export interface IUserRepository { findOneByEmail(email: string): Promise; findById(id: Types.ObjectId): Promise; create( createUserDto: Pick, ): Promise; } Here, each method clearly promises a “live” Mongoose document (with built-in methods) while elsewhere you can rely on User for pure data shapes—keeping your boundaries and types crystal clear. Let’s connect!!:

When working with Mongoose and TypeScript, two helper types make your life much easier:
/**
* Extracts the “plain” shape of your schema—
* just the fields you defined, without Mongoose’s built-in methods or `_id`.
*/
export type User = InferSchemaType<typeof userSchema>;
/**
* Represents a fully “hydrated” Mongoose document:
* your fields plus all of Mongoose’s methods and metadata
* (e.g. `_id`, `save()`, `populate()`, etc.).
*/
export type UserDocument = HydratedDocument<User>;
export const userModel = model<UserDocument>("user", userSchema);
InferSchemaType
• Produces a pure TypeScript type from your schema definition.
• Use it whenever you need just the data shape (e.g. DTOs, service inputs/outputs).
HydratedDocument
• Wraps your base type T with Mongoose’s document helpers.
• Use it for any function that deals with real, database-backed
documents (e.g. returns from find, create, save).
For example, in a repository interface you might write:
export interface IUserRepository {
findOneByEmail(email: string): Promise<UserDocument>;
findById(id: Types.ObjectId): Promise<UserDocument>;
create(
createUserDto: Pick<CreateUserDto, 'email' | 'password'>,
): Promise<UserDocument>;
}
Here, each method clearly promises a “live” Mongoose document (with built-in methods) while elsewhere you can rely on User for pure data shapes—keeping your boundaries and types crystal clear.
Let’s connect!!: