Definitelytyped: @types/mongodb - Generics does not work with v3.2.x or v3.3.x

Created on 23 Oct 2019  路  5Comments  路  Source: DefinitelyTyped/DefinitelyTyped

Using generics to set the schema does not seem to work since v3.2.x of @types/mongodb

See this example using @types/mongodb v3.1.32 (works):
https://codesandbox.io/s/typesmongodb-3132-works-nmxbc

See this example using @types/mongodb v3.3.6 (type error):
https://codesandbox.io/s/typesmongodb-336-type-error-onshs

Reproduction (same as CodeSandbox):

import { Db, Collection } from "mongodb";

export default class Model<Schema extends { _id: string }> {
  private readonly db: Db;
  private readonly collection: Collection<Schema>;

  public constructor(db: Db, collectionName: string) {
    this.db = db;
    this.collection = db.collection(collectionName);
  }

  public findOneById(id: string) {
    // This gives the type error below on @types/mongodb v3.3.6
    return this.collection.findOne({ _id: id });
  }
}

TS Error:

Argument of type '{ _id: string; }' is not assignable to parameter of type 'FilterQuery<Schema>'.
  Type '{ _id: string; }' is not assignable to type '{ [P in keyof Schema]?: MongoAltQuery<Schema[P]> | QuerySelector<MongoAltQuery<Schema[P]>> | undefined; }'.

Authors: @CaselIT @alanmarcell @bitjson @dante-101 @mcortesi @EnricoPicci @AJCStriker @julien-c @daprahamian @denys-bushulyak @BastienAr @sindbach @geraldinelemeur @jishi @various89 @angela-1 @hector7 @floric @erikc5000 @Manc @jloveridge @ranguna @HosseinAgha @albertossilva

Most helpful comment

Agreed, this is definitely a bug! If you guys put a bug into the TypeScript repo then please don't forget to reference this PR. I'd love to see where this goes.

My demo code: typescriptlang.org

All 5 comments

Hi @lirbank,
This looks to me like a TypeScript mapped types bug.
I can confirm that this does __not__ work:

  const genericFunc = async <Schema extends { _id: string }>() => {
    type a = { [P in keyof Schema]: Schema[P] };
    const b: a = { _id: 'sd' };
  }

And this does work:

  type Schema2 = { _id: string };
  type a2 = { [P in keyof Schema2]: Schema2[P] };
  const b2: a2 = { _id: 'sd' };

We've implement collection.find types using mapped types.
There is not much that we can do here. I think you should open (look for) a TypeScript issue.
I have to admit that you are doing a pretty complicated job with TypeScript generics (generic on top of generic on top of generic 馃槃) and TypeScript is an awesome language that even lets you handle these scenarios.

Agreed, this is definitely a bug! If you guys put a bug into the TypeScript repo then please don't forget to reference this PR. I'd love to see where this goes.

My demo code: typescriptlang.org

Grrrrr I found the same issue using a generic service. :/ TypeScript has been a little "dumber" lately it seems. For a workaround I just asserted using as:

collection.findOne({id: 2 } as FilterQuery<Entity<T>>, (error, result) => {

                    })

Hi @lirbank,
According to (your issue) https://github.com/microsoft/TypeScript/issues/35077 and (my issue) https://github.com/microsoft/TypeScript/issues/35647 TypeScript (and mongo typings) work as expected in this scenario.
I don't think our mongo driver generics can work with other generics in a format that you expect them to. __We need the keyof Schema__ in order to generate right typing for mongo methods and keyof does not have enough information about the generic type in this scenario (checkout https://github.com/microsoft/TypeScript/issues/35647#issuecomment-566543066).
I think we have enough workarounds (including yours) for this issue to close.

Hi @HosseinAgha - I agree, looks like we're at the end of the road with this one.

Thanks for looking into it!

Was this page helpful?
0 / 5 - 0 ratings