Skip to content

Aggregation Typing not working as expected #166

Description

@jeff-titan

Hey! Love the project, really hope Papr makes it big!

I'm trying to figure out how to get proper typing out of the aggregation pipeline. Docs reference that says this is possible:
https://plexinc.github.io/papr/#/api/model?id=aggregate

Returns:
Promise<Array<Aggregate>> A custom data type based on the pipeline steps

Given these two models:

import { types, schema } from 'papr';
import papr from '@db/papr';

export enum Kind {
  dog = 'dog',
  cat = 'cat',
}

const petSchema = schema({
  name: types.string({ required: true }),
  owner: types.objectId({ required: true }),
  kind: types.enum(Object.values(Kind), { required: true }),
});

export type PetDocument = typeof petSchema[0];

const Pet = papr.model('pets', petSchema);

export default Pet;
import { types, schema } from 'papr';
import papr from '@db/papr';

const ownerSchema = schema({
  firstName: types.string({ required: true }),
  lastName: types.string({ required: true }),
  address: types.object(
    {
      line1: types.string({ required: true }),
      line2: types.string(),
      city: types.string({ required: true }),
      state: types.string({ required: true }),
      zip: types.string({ required: true }),
      country: types.string({ required: true }),
    },
    { required: true }
  ),
  phoneNumber: types.string(),
});

export type OwnerDocument = typeof ownerSchema[0];

const Owner = papr.model('owners', ownerSchema);

export default Owner;

I would expect the below snippet to return a type where owner is fully enumerated, but I'm still seeing that it's type ObjectId. Actually the entire return type of the pipeline is just PetDocument.
When I add a project stage to this pipeline and try and select only a few fields, it also doesn't change the return type.

This does work at runtime as expected (ie I can get the owner.address off of the $lookup => $unwind). We just don't get type hinting from tooling and actually gives us some tsc errors (even though, again, it works at runtime).

async function findPetsByOwnerState(state: string) {
  const res = await Pet.aggregate([
    {
      $lookup: {
        from: 'owners',
        localField: 'owner',
        foreignField: '_id',
        as: 'owner',
      },
    },
    {
      $unwind: '$owner',
    },
    {
      $match: {
        'owner.address.state': state,
      },
    }
  ]);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions