v3.3.1
Playground
Getting Started

Model and Input Types

Choose types for new input and stored Mongoose documents without requiring a generated ID in requests.

Model and Input Types

Mongoose adds _id to a stored document. A create request normally does not contain it. Use InferInput for data you accept and InferDocument for a persisted document.

The createUser() function below requires an active MongoDB connection when you call it.

user-types.ts
import mongoose from 'mongoose';
import {z} from 'zod/v4';
import {toMongooseSchema, zObjectId} from '@nullix/zod-mongoose';
import type {InferDocument, InferInput} from '@nullix/zod-mongoose';

const UserReadSchema = z.object({
  _id: zObjectId(),
  name: z.string().min(2),
});
const CreateUserSchema = UserReadSchema.omit({_id: true});

type CreateUserInput = InferInput<typeof CreateUserSchema>;
type UserDocument = InferDocument<typeof UserReadSchema>;

const UserModel = mongoose.model('User', toMongooseSchema(UserReadSchema));

async function createUser(input: CreateUserInput) {
  const user = await UserModel.create(CreateUserSchema.parse(input));
  UserReadSchema.parse(user.toObject()); // Validate the stored shape.
  return user;
}

CreateUserSchema accepts { name: 'Ada' }; Mongoose generates _id when it creates the document. UserDocument['_id'] is typed as an ObjectId, and the read schema can validate data returned from Mongoose. If you only need Mongoose's automatic ID and do not validate read objects with Zod, you can omit _id from the Zod schema, as in Start Here.

InferDocument<T> adds a root ObjectId to the type. It does not recursively add IDs to nested Zod objects, and it does not inspect metadata such as { _id: false }. Check the nested object guide when modeling embedded documents.