diff --git a/src/__tests__/model.test.ts b/src/__tests__/model.test.ts index 0544afdb8..efae727a9 100644 --- a/src/__tests__/model.test.ts +++ b/src/__tests__/model.test.ts @@ -1075,6 +1075,18 @@ describe('model', () => { } }); + test('with invalid projection', async () => { + await simpleModel.find( + {}, + { + projection: { + // @ts-expect-error `nested.baz` is not present on the schema + 'nested.baz': 1, + }, + } + ); + }); + test('with projection, re-assignable to Pick type', async () => { let results = await simpleModel.find({}, { projection }); diff --git a/src/model.ts b/src/model.ts index f2384d50a..0d544e2e9 100644 --- a/src/model.ts +++ b/src/model.ts @@ -78,32 +78,32 @@ export interface Model, 'limit' | 'projection' | 'skip' | 'sort'> ) => Promise; - find: | undefined>( + find: | undefined>( filter: PaprFilter, options?: Omit, 'projection'> & { projection?: TProjection } ) => Promise[]>; - findById: | undefined>( + findById: | undefined>( id: TSchema['_id'] | string, options?: Omit, 'projection'> & { projection?: TProjection } ) => Promise | null>; - findCursor: | undefined>( + findCursor: | undefined>( filter: PaprFilter, options?: Omit, 'projection'> & { projection?: TProjection } ) => Promise>>; - findOne: | undefined>( + findOne: | undefined>( filter: PaprFilter, options?: Omit, 'projection'> & { projection?: TProjection } ) => Promise | null>; - findOneAndDelete: | undefined>( + findOneAndDelete: | undefined>( filter: PaprFilter, options?: Omit & { projection?: TProjection } ) => Promise | null>; - findOneAndUpdate: | undefined>( + findOneAndUpdate: | undefined>( filter: PaprFilter, update: PaprUpdateFilter, options?: Omit & { projection?: TProjection } @@ -131,7 +131,7 @@ export interface Model Promise; - upsert: | undefined>( + upsert: | undefined>( filter: PaprFilter, update: PaprUpdateFilter, options?: Omit & { projection?: TProjection } @@ -622,7 +622,7 @@ export function build | undefined>( + async function find | undefined>( filter: PaprFilter, options?: Omit, 'projection'> & { projection?: TProjection } ): Promise[]> { @@ -664,7 +664,7 @@ export function build | undefined>( + async function findById | undefined>( id: TSchema['_id'] | string, options?: Omit, 'projection'> & { projection?: TProjection } ): Promise | null> { @@ -703,7 +703,7 @@ export function build | undefined, + TProjection extends Projection | undefined, >(filter: PaprFilter, options?: Omit, 'projection'> & { projection?: TProjection }): Promise< FindCursor> > { @@ -742,7 +742,7 @@ export function build | undefined>( + async function findOne | undefined>( filter: PaprFilter, options?: Omit, 'projection'> & { projection?: TProjection } ): Promise | null> { @@ -768,7 +768,7 @@ export function build | undefined>( + model.findOneAndDelete = wrap(model, async function findOneAndDelete | undefined>( filter: PaprFilter, options?: Omit & { projection?: TProjection } ): Promise | null> { @@ -812,7 +812,7 @@ export function build | undefined>( + model.findOneAndUpdate = wrap(model, async function findOneAndUpdate | undefined>( filter: PaprFilter, update: PaprUpdateFilter, options?: Omit & { projection?: TProjection } @@ -1051,7 +1051,9 @@ export function build | undefined>( + model.upsert = async function upsert< + TProjection extends Projection | undefined, + >( filter: PaprFilter, update: PaprUpdateFilter, options?: Omit & { projection?: TProjection } diff --git a/src/utils.ts b/src/utils.ts index 26ec03df8..717fcc89c 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -134,7 +134,7 @@ type FilterProperties = Pick, []>, '.'>, number>> + | ExactPartial, []>, '.'>, number>> | undefined, > = undefined extends Projection ? WithId @@ -147,9 +147,19 @@ export type ProjectionType< keyof FilterProperties >; -export type Projection = Partial< - Record, []>, '.'>, number> ->; +type ExactPartial = { + [K in keyof Subset]: K extends keyof BaseObject + ? BaseObject[K] extends Record + ? ExactPartial + : BaseObject[K] + : never; +}; + +export type Projection< + TProjection, + TSchema, + TPaths = Record, []>, '.'>, number>, +> = ExactPartial; export type PropertyNestedType< Type,