-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: Improve projection type safety #712
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,32 +78,32 @@ export interface Model<TSchema extends BaseSchema, TOptions extends SchemaOption | |
options?: Omit<FindOptions<TSchema>, 'limit' | 'projection' | 'skip' | 'sort'> | ||
) => Promise<boolean>; | ||
|
||
find: <TProjection extends Projection<TSchema> | undefined>( | ||
find: <TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TIL that you can use the same generic identifier in both the left side and right side of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Circular generic constraints are really interesting and make quite a bit of sense, but they only currently work when they're non-immediate. Definitely pushes the boundaries of what TypeScript is able to deliver. Here is a really good thread if you want to read a bit more about them. And there is a recursion limit, but it's pretty sizable and we'd hit that when building the schema path options already if we were going to hit it, so there's no additional risk here. |
||
filter: PaprFilter<TSchema>, | ||
options?: Omit<FindOptions<TSchema>, 'projection'> & { projection?: TProjection } | ||
) => Promise<ProjectionType<TSchema, TProjection>[]>; | ||
|
||
findById: <TProjection extends Projection<TSchema> | undefined>( | ||
findById: <TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
id: TSchema['_id'] | string, | ||
options?: Omit<FindOptions<TSchema>, 'projection'> & { projection?: TProjection } | ||
) => Promise<ProjectionType<TSchema, TProjection> | null>; | ||
|
||
findCursor: <TProjection extends Projection<TSchema> | undefined>( | ||
findCursor: <TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
filter: PaprFilter<TSchema>, | ||
options?: Omit<FindOptions<TSchema>, 'projection'> & { projection?: TProjection } | ||
) => Promise<FindCursor<ProjectionType<TSchema, TProjection>>>; | ||
|
||
findOne: <TProjection extends Projection<TSchema> | undefined>( | ||
findOne: <TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
filter: PaprFilter<TSchema>, | ||
options?: Omit<FindOptions<TSchema>, 'projection'> & { projection?: TProjection } | ||
) => Promise<ProjectionType<TSchema, TProjection> | null>; | ||
|
||
findOneAndDelete: <TProjection extends Projection<TSchema> | undefined>( | ||
findOneAndDelete: <TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
filter: PaprFilter<TSchema>, | ||
options?: Omit<FindOneAndDeleteOptions, 'projection'> & { projection?: TProjection } | ||
) => Promise<ProjectionType<TSchema, TProjection> | null>; | ||
|
||
findOneAndUpdate: <TProjection extends Projection<TSchema> | undefined>( | ||
findOneAndUpdate: <TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
filter: PaprFilter<TSchema>, | ||
update: PaprUpdateFilter<TSchema>, | ||
options?: Omit<FindOneAndUpdateOptions, 'projection'> & { projection?: TProjection } | ||
|
@@ -131,7 +131,7 @@ export interface Model<TSchema extends BaseSchema, TOptions extends SchemaOption | |
options?: UpdateOptions | ||
) => Promise<UpdateResult>; | ||
|
||
upsert: <TProjection extends Projection<TSchema> | undefined>( | ||
upsert: <TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
filter: PaprFilter<TSchema>, | ||
update: PaprUpdateFilter<TSchema>, | ||
options?: Omit<FindOneAndUpdateOptions, 'projection' | 'upsert'> & { projection?: TProjection } | ||
|
@@ -622,7 +622,7 @@ export function build<TSchema extends BaseSchema, TOptions extends SchemaOptions | |
// prettier-ignore | ||
model.find = wrap( | ||
model, | ||
async function find<TProjection extends Projection<TSchema> | undefined>( | ||
async function find<TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
filter: PaprFilter<TSchema>, | ||
options?: Omit<FindOptions<TSchema>, 'projection'> & { projection?: TProjection } | ||
): Promise<ProjectionType<TSchema, TProjection>[]> { | ||
|
@@ -664,7 +664,7 @@ export function build<TSchema extends BaseSchema, TOptions extends SchemaOptions | |
// prettier-ignore | ||
model.findById = wrap( | ||
model, | ||
async function findById<TProjection extends Projection<TSchema> | undefined>( | ||
async function findById<TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
id: TSchema['_id'] | string, | ||
options?: Omit<FindOptions<TSchema>, 'projection'> & { projection?: TProjection } | ||
): Promise<ProjectionType<TSchema, TProjection> | null> { | ||
|
@@ -703,7 +703,7 @@ export function build<TSchema extends BaseSchema, TOptions extends SchemaOptions | |
* } | ||
*/ | ||
model.findCursor = wrap(model, async function findCursor< | ||
TProjection extends Projection<TSchema> | undefined, | ||
TProjection extends Projection<TProjection, TSchema> | undefined, | ||
>(filter: PaprFilter<TSchema>, options?: Omit<FindOptions<TSchema>, 'projection'> & { projection?: TProjection }): Promise< | ||
FindCursor<ProjectionType<TSchema, TProjection>> | ||
> { | ||
|
@@ -742,7 +742,7 @@ export function build<TSchema extends BaseSchema, TOptions extends SchemaOptions | |
// prettier-ignore | ||
model.findOne = wrap( | ||
model, | ||
async function findOne<TProjection extends Projection<TSchema> | undefined>( | ||
async function findOne<TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
filter: PaprFilter<TSchema>, | ||
options?: Omit<FindOptions<TSchema>, 'projection'> & { projection?: TProjection } | ||
): Promise<ProjectionType<TSchema, TProjection> | null> { | ||
|
@@ -768,7 +768,7 @@ export function build<TSchema extends BaseSchema, TOptions extends SchemaOptions | |
* const user = await User.findOneAndDelete({ firstName: 'John' }); | ||
*/ | ||
// prettier-ignore | ||
model.findOneAndDelete = wrap(model, async function findOneAndDelete<TProjection extends Projection<TSchema> | undefined>( | ||
model.findOneAndDelete = wrap(model, async function findOneAndDelete<TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
filter: PaprFilter<TSchema>, | ||
options?: Omit<FindOneAndDeleteOptions, 'projection'> & { projection?: TProjection } | ||
): Promise<ProjectionType<TSchema, TProjection> | null> { | ||
|
@@ -812,7 +812,7 @@ export function build<TSchema extends BaseSchema, TOptions extends SchemaOptions | |
* userProjected.lastName; // valid | ||
*/ | ||
// prettier-ignore | ||
model.findOneAndUpdate = wrap(model, async function findOneAndUpdate<TProjection extends Projection<TSchema> | undefined>( | ||
model.findOneAndUpdate = wrap(model, async function findOneAndUpdate<TProjection extends Projection<TProjection, TSchema> | undefined>( | ||
filter: PaprFilter<TSchema>, | ||
update: PaprUpdateFilter<TSchema>, | ||
options?: Omit<FindOneAndUpdateOptions, 'projection'> & { projection?: TProjection } | ||
|
@@ -1051,7 +1051,9 @@ export function build<TSchema extends BaseSchema, TOptions extends SchemaOptions | |
* userProjected.firstName; // TypeScript error | ||
* userProjected.lastName; // valid | ||
*/ | ||
model.upsert = async function upsert<TProjection extends Projection<TSchema> | undefined>( | ||
model.upsert = async function upsert< | ||
TProjection extends Projection<TProjection, TSchema> | undefined, | ||
>( | ||
filter: PaprFilter<TSchema>, | ||
update: PaprUpdateFilter<TSchema>, | ||
options?: Omit<FindOneAndUpdateOptions, 'projection' | 'upsert'> & { projection?: TProjection } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please combine some valid properties with this invalid one here?