Skip to content

TypeScript: Optional fields with default: null incorrectly remove | null from inferred type #15878

@skrukwa

Description

@skrukwa

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

9.0.1

Node.js version

24.11.0

MongoDB server version

n/a

Typescript version (if applicable)

No response

Description

When an optional field has default: null in the schema definition, the TypeScript type inference removes | null from the field's type. This creates a type mismatch where the field can actually be null at runtime, but TypeScript thinks it cannot be.

This appears to be caused by the IsPathRequired type logic treating any field with a non-undefined default as "required", which prevents | null from being added to the type, even when the default value itself is null.


ALSO, as a side note, I think that users should be allowed to configure whether they want inferred types to include | null for ANY type (even optional ones) unless explicitly included. Maybe an option inside interface DefaultSchemaOptions?

My rational is that when users create separate interfaces and use them to define their schema instead of using automatic type inference, I very rarely see people include | null for EVERY OPTIONAL TYPE. Despite it being possible for null values to be stored, most users do not want to deal with it in their types. I guess this relates to #14421. Let me know if I should make a separate issue for this thought.

Steps to Reproduce

const UserSchema = new Schema({
  name: { type: String, default: null }
});

type RawUser = InferRawDocTypeFromSchema<typeof UserSchema>;
// type RawUser = {
//     name: string;
// }

type HydratedUser = InferHydratedDocTypeFromSchema<typeof UserSchema>;
// type HydratedUser = mongoose.Document<unknown, {}, {
//     name: string;
// }, {
//     id: string;
// }, mongoose.ResolveSchemaOptions<mongoose.DefaultSchemaOptions>> & Omit<{
//     user: string;
// } & {
//     _id: mongoose.Types.ObjectId;
// } & {
//     __v: number;
// }, "id"> & {
//     id: string;
// }

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

const user = new UserModel({});
console.log(user.name)
// null

Expected Behavior

The inferred types should include | null.

type RawUser = {
    name: string | null;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions