Uploaded image for project: 'Node.js Driver'
  1. Node.js Driver
  2. NODE-4470

Replace OptionalUnlessRequiredId with something less awkward

    • Type: Icon: Improvement Improvement
    • Resolution: Unresolved
    • Priority: Icon: Unknown Unknown
    • None
    • Affects Version/s: None
    • Component/s: TypeScript

      When creating a new document using insertOne(), most users prefer for MongoDB to automatically assign a unique document _id. For example, if my document looks like this...

      // Life before PR 3077
      interface Book {
        _id: ObjectId;
        title: string
      }
      

      ...then I might call insertOne({title: 'My Book'}), omitting the _id field, which was optional in this context.

      However, a minority of users sometimes want to specify this _id explicitly. To help that minority of users some of the time, PR node-mongodb-native#3077 introduced a safeguard for enforcing that the _id must always be specified when calling insertOne().

      Unfortunately, this new safeguard is controlled by the Book._id declaration: To get the behavior that most users want, we must now change our interface declaration to be like this:

      // Life after PR 3077
      interface Book {
        // This must be optional, otherwise insertOne() will require the _id
        _id?: ObjectId; 
        title: string
      }
      

      This is unfortunate:

      1. This optional Book._id field does not accurately represents the real document: Every MongoDB document always has an _id. (Note that the input to insertOne() is NOT a document, it is a partial input used to initialize a new document.)
      2. Everywhere that we previously wrote Book, now we must write WithId\<Book\>. Otherwise I cannot read the _id field without adding annoying tests/casts for the impossible undefined state. This effect cascades across every document in our entire code base. Another developer voiced the same concern in 3077#issuecomment

      I understand that PR 3077 was a nice improvement for a minority of users sometimes. But is there a way to accomplish that goal without making things worse for everyone else?

      Technical details

      In the new implementation, this policy is controlled by this declaration:

      export declare type OptionalUnlessRequiredId<TSchema> = TSchema extends {
          _id: any;
      } ? TSchema : OptionalId<TSchema>;
      

      Ideas for improvements

      • Maybe instead of {{TSchema extends { _id: any; }}}, the we check for some kind of _id: RequiredOnInsert<TSchema>.
      • Maybe Collection<T> could have a parameterization as Collection<T, IdRequiredOnInsert> or CollectionWithExplicitId<T>
      • Just revert PR #3077 if it causes more problems than it solves

      Maybe other people have better suggestions.

            Assignee:
            Unassigned Unassigned
            Reporter:
            pete.gonzalez@octogonz.com Pete Gonzalez
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: