Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript does not complain about type issues when returning doc.toObject() #12883

Closed
2 tasks done
twiddler opened this issue Jan 6, 2023 · 2 comments
Closed
2 tasks done
Labels
typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@twiddler
Copy link

twiddler commented Jan 6, 2023

Prerequisites

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

Mongoose version

6.8.3

Node.js version

n/a

MongoDB server version

n/a

Typescript version (if applicable)

4.9.4

Description

I am having a hard time understanding why TypeScript complains in getUser_1 and getUser_3 seen below, but not in getUser_2.

Is this an issue with mongoose?

Steps to Reproduce

import mongoose from 'mongoose'

const userSchema = new mongoose.Schema({
    name: String,
})

const UserModel = mongoose.model('User', userSchema)

type GetUserOutput = {
    _id: string
    firstname?: string
}

async function getUser_1(): Promise<GetUserOutput> {
    const user = await UserModel.findOne({}).exec()

    if (user === null) throw new Error(`No user found.`)

    return user // TypeScript complains:
    // Type 'Document<unknown, any, { name?: string | undefined; }> & { name?: string | undefined; } & { _id: ObjectId; }' is not assignable to type 'GetUserOutput'.
    //   Types of property '_id' are incompatible.
    //     Type 'ObjectId' is not assignable to type 'string'.ts(2322)
}

async function getUser_2(): Promise<GetUserOutput> {
    const user = await UserModel.findOne({}).exec()

    if (user === null) throw new Error(`No user found.`)

    return user.toObject() // TypeScript does not complain.
}

async function getUser_3(): Promise<GetUserOutput> {
    const user = await UserModel.findOne({}).exec()

    if (user === null) throw new Error(`No user found.`)

    const o = user.toObject()

    return o // TypeScript complains:
    // Type 'LeanDocument<{ name?: string | undefined; }> & { _id: ObjectId; }' is not assignable to type '{ firstname?: string | undefined; _id: string; }'.
    //   Types of property '_id' are incompatible.
    //     Type 'ObjectId' is not assignable to type 'string'.ts(2322)
}

Expected Behavior

TypeScript should complain in getUser_2, too.

@IslandRhythms IslandRhythms added the typescript Types or Types-test related issue / Pull Request label Jan 9, 2023
@IslandRhythms
Copy link
Collaborator

The issue is that while you define _id to be a string in type GetUserOutput, the schema definition has it as an objectId. As a result, converting to an object makes it stop complaining because the types match. If you add _id: String to your schema definition you will see that typescript stops complaining.

@twiddler
Copy link
Author

twiddler commented Jan 9, 2023

Thanks for your help, but this is not what my issue is about. My issue is about TypeScript not complaining in the 2nd case.

@vkarpov15 vkarpov15 modified the milestones: 6.8.5, 6.8.6 Jan 20, 2023
@vkarpov15 vkarpov15 modified the milestones: TypeScript backlog, 8.6 Aug 19, 2024
vkarpov15 added a commit that referenced this issue Aug 20, 2024
types: make toObject() and toJSON() not generic by default to avoid type widening
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
typescript Types or Types-test related issue / Pull Request
Projects
None yet
Development

No branches or pull requests

3 participants