使用MongoDB Node.js的updateOne方法时出现TypeScript编译时错误
updateOne Let's walk through what's causing this compilation error and fix it step by step:
What's Going Wrong?
Your TS error code 2769 stems from two key issues:
- Incorrect
updateOneusage: Mongoose'supdateOnerequires two core arguments: first a filter to target the specific document you want to update, then the update payload. Right now you're only passing the update fields, so TypeScript is treating that object as the filter (which doesn't match the expected type for your user model). - Type mismatch from optional chaining: Your code uses
updatePayLoad.data?.firstName, which makes those fieldsstring | undefined. But your Mongoose model definesfirstName/lastNameas requiredstringfields, and withexactOptionalPropertyTypes: trueenabled, TypeScript blocks assigningundefinedto non-optional properties.
Additionally, your Zod schema marks all three fields as required—if this is a partial update endpoint (where users can update just one or two fields), that schema needs adjustment too.
Step-by-Step Fixes
1. Correct the updateOne Parameter Order
First, add a filter to target the specific user you want to update (like their _id or email). Here's the proper structure:
// Example: Use user ID as the filter (adjust based on how you identify users) const response = await userModel.updateOne( { _id: userId }, // 1. Filter: Which user should be updated? { firstName: updatePayLoad.data.firstName, lastName: updatePayLoad.data.lastName, password: hashedPassword }, // 2. Update: What fields to modify? { new: true } // Optional: Return the updated document instead of the original );
2. Resolve the undefined Type Issue
Since you're using Zod for validation, leverage it to guarantee your fields aren't undefined:
// First, validate the payload with your Zod schema const validatedData = updateValidation.parse(updatePayLoad.data); // Now validatedData has guaranteed string values (no undefined) const hashedPassword = await bcrypt.hash(validatedData.password, 10); // Adjust hashing logic as needed const response = await userModel.updateOne( { _id: userId }, { $set: { // Using $set is Mongoose's recommended way to update specific fields firstName: validatedData.firstName, lastName: validatedData.lastName, password: hashedPassword } } );
If this is a partial update endpoint (allowing users to skip some fields), modify your Zod schema to make fields optional, then filter out undefined values:
// Update Zod schema for partial updates export const updateValidation = z.object({ firstName: z.string().optional(), lastName: z.string().optional(), password: z.string().optional() }); // Validate and filter out undefined fields const validatedData = updateValidation.parse(updatePayLoad.data); const updateFields = Object.fromEntries( Object.entries(validatedData).filter(([_, value]) => value !== undefined) ); // Add hashed password if it's provided (or make it required if needed) if (validatedData.password) { updateFields.password = await bcrypt.hash(validatedData.password, 10); } // Run the update const response = await userModel.updateOne( { _id: userId }, { $set: updateFields } );
3. Optional: Adjust TypeScript Config (Not Recommended)
If you want a quick fix without changing code, you can disable exactOptionalPropertyTypes in your tsconfig.json—but this removes a useful type safety check, so fixing the code is the better long-term solution:
{ "compilerOptions": { "exactOptionalPropertyTypes": false } }
Final Working Example (Full Update)
Here's a clean version assuming you're requiring all three fields:
import { updateValidation } from "../your-schema-path"; import bcrypt from "bcrypt"; // Inside your route handler const validatedData = updateValidation.parse(req.body.data); // Adjust based on your payload structure const hashedPassword = await bcrypt.hash(validatedData.password, 10); const updatedUser = await userModel.updateOne( { _id: req.user.id }, // Assume you get the user ID from auth middleware { $set: { firstName: validatedData.firstName, lastName: validatedData.lastName, password: hashedPassword } }, { new: true } ); res.status(200).json(updatedUser);
内容的提问来源于stack exchange,提问作者Adarsh Singh

