Definitelytyped: Letting mongodb pick the _id is not possible anymore when typing collections.

Created on 9 Mar 2019  路  2Comments  路  Source: DefinitelyTyped/DefinitelyTyped

  • [x] I tried using the @types/mongodb package and had problems.
  • [x] I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
  • [x] I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).
  • [x] [Mention](https://github.com/blog/821-mention-somebody-they-re-notified) the authors (see Definitions by: in index.d.ts) so they can respond.

    • @CaselIT

    • @alanmarcell

    • @bitjson

    • @dante-101

    • @mcortesi

    • @EnricoPicci

    • @AJCStriker

    • @julien-c

    • @daprahamian

    • @denys-bushulyak

    • @BastienAr

    • @sindbach

    • @geraldinelemeur

    • @jishi

    • @various89

    • @angela-1

    • @lirbank

    • @hector7

    • @floric

    • @erikc5000

    • @Manc

Since this PR
Collection.insert{,One,Many} are typed with TSchema from Collection<TSchema>
same as the return type of the query methods. This makes it a bit hard to use
when you want mongodb to pick the _id of an inserted document for you:

Version with _id being part of the TSchema:

import { Collection, MongoClient, ObjectId } from 'mongodb'

interface Person {
  _id: ObjectId
  name: string 
  age: number
}

MongoClient.connect().then(async client => {
  const db = client.db()
  const personCollection: Collection<Person> = db.collection('persons');

  const writeResult = await personCollection.insertOne({ name: "Foo Bar", age: 30 }) // type error, `_id` missing

  const person = await personCollection.findOne({ _id: writeResult.insertedId })

  if (person) {
    console.log(person._id);
  }
})

Version without _id being part of the TSchema:

import { Collection, MongoClient, ObjectId } from 'mongodb'

interface Person {
  name: string 
  age: number
}

MongoClient.connect().then(async client => {
  const db = client.db()
  const personCollection: Collection<Person> = db.collection('persons');

  const writeResult = await personCollection.insertOne({ name: "Foo Bar", age: 30 }) 

  const person = await personCollection.findOne({ _id: writeResult.insertedId })

  if (person) {
    console.log(person._id); // type error, _id is not defined
  }
})

In either case it's not possible to sensibly type collections anymore :(

I think it would make sense to make the _id property optional for the inserts.
I can make a PR I just wanted to ask for feedback first.

Most helpful comment

Perhaps we could just use

type TSchemaInsert<TSchema> = Omit<TSchema, '_id'> & { _id?: any }

All 2 comments

Hi @despairblue,

Personally, I declare _id optional in my schemas, e.g.:

interface Person {
    _id?: ObjectId;
    name: string ;
    age: number;
}

This works okay for me, but it could be better since _id is not really optional, it just depends on the use case. Like you said, it's optional for inserts, but to my knowledge it's always included in find* results, whereas other properties may become optional if projection is used.

I think a PR in that direction (with a few tests in mongodb-tests.ts) would be great.

Perhaps we could just use

type TSchemaInsert<TSchema> = Omit<TSchema, '_id'> & { _id?: any }
Was this page helpful?
0 / 5 - 0 ratings