Skip to content

Type-safe .populate method #16010

@akim-bow

Description

@akim-bow

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the feature has not already been requested

🚀 Feature Proposal

I've been working with mongoose for some time, coming from TypeScript world.
While working with query population and manually typing them I was thinking why a user need to manually provide types when types could be inferred from passed parameters.

Then i decided to implement that type by myself and came to working solution which looks like this:
https://gist.github.com/akim-bow/76c1d7243c3362302a8cf286ff78e409
It's not finished and lacks some functionality, but still could be used for type inference and works fast.

And my proposal is why not to implement something like this in mongoose? So TypeScript users will be able to receive type safe results from queries. Of course, it's still requires to type schema interfaces correctly, but significantly reduce error margin by not relying on user provided type casts.

if this seems like an interesting feature i can take an ownership of this feature, polish it and present as a PR. If not... please explain why not to add such good thing to mongoose.

Motivation

Improve type safety of TS projects utilizing mongoose.

Example

export interface IOrder {
	route: mongoose.Types.ObjectId;
}

const Order = model<IOrder>('order', new Schema<IOrder>(
	{
		route: {
			type: Schema.Types.ObjectId,
			ref: "Route",
			required: true,
		},
	}
));

export interface IRoute {
	_id: Types.ObjectId;
	from: {
		currency: Types.ObjectId;
	}
}

const Route = model<IRoute>('route', new Schema<IRoute>(
	{
		from: {
			currency: {
				type: Schema.Types.ObjectId,
				ref: "Currency",
				required: true,
			},
		}
	}
));

export interface ICurrency {
	_id: Types.ObjectId;
	name: string;
	symbol: string;
}

const Currency = model<ICurrency>('currency', new Schema<ICurrency>(
	{
		name: {
			type: String,
			required: true,
		},
		symbol: {
			type: String,
			required: true,
		}
	}
));

// Defined in gist provided in https://github.com/Automattic/mongoose/issues/16010
const res = await populateModel(Order.findOne({ _id: 'asda'}), {
	model: Route,
	path: 'route',
	populate: [{
		model: Currency,
		path: 'from.currency',
		select: 'symbol'
	}]
}).lean();


const resolvedType = res?.route?.from?.currency?.symbol; // string | undefined

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementThis issue is a user-facing general improvement that doesn't fix a bug or add a new featurenew featureThis change adds new functionality, like a new method or class

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions