stalniy / ucast

Conditions query translator for everything
Apache License 2.0
197 stars 20 forks source link

typing limitation when using $in on a array property #48

Open socnacom opened 2 months ago

socnacom commented 2 months ago

Hi!

If I write :

    import type { MongoQuery } from '@ucast/mongo2js';
    import type { Types as MongooseTypes } from 'mongoose';

    export type Id = MongooseTypes.ObjectId;

    interface User {
        // ....
        readonly globalRoleIds: readonly Id[];
    }

    // ....
    const mongoQuery: MongoQuery<User> = {
      globalRoleIds: {
        $in: [adminRole._id],
      },
    };

I've got :

Type '{ $in: Types.ObjectId[]; }' is not assignable to type '(MongoQueryFieldOperators<User> & MongoQueryTopLevelOperators<User>) | OperatorValues<readonly ObjectId[]> | undefined'.
  Types of property '$in' are incompatible.
    Type 'ObjectId[]' is not assignable to type '(readonly ObjectId[])[] | User[] | undefined'.
      Type 'ObjectId[]' is not assignable to type '(readonly ObjectId[])[]'.
        Type 'ObjectId' is missing the following properties from type 'readonly ObjectId[]': length, concat, join, slice, and 26 more.ts(2322)
user.entity.ts(62, 12): The expected type comes from property 'globalRoleIds' which is declared here on type 'Query<User, MongoQueryFieldOperators<User> & MongoQueryTopLevelOperators<User>> & MongoQueryTopLevelOperators<...>'

This error is because globalRoleIds is a list of ids.

So i have to cast my query by doing as unknown as MongoQuery<User>; which limits interest of query type.

Do you have a better alternative ?

Thank you

stalniy commented 2 months ago

Nice catch! I think it’s a bug. I’ll take a closer look and fix it. Operators that support arrays should infer their type a bit differently