Skip to content

Commit

Permalink
Merge branch 'main' of git://github.com/mohammad0-0ahmad-forks/mongoo…
Browse files Browse the repository at this point in the history
…se into mohammad0-0ahmad-forks-main
  • Loading branch information
vkarpov15 committed Mar 11, 2022
2 parents 9ea1201 + 2c04ac9 commit 7ce083d
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 5 deletions.
32 changes: 31 additions & 1 deletion test/types/populate.test.ts
@@ -1,7 +1,7 @@
import { Schema, model, Document, PopulatedDoc, Types, HydratedDocument } from 'mongoose';
// Use the mongodb ObjectId to make instanceof calls possible
import { ObjectId } from 'mongodb';
import { expectError } from 'tsd';
import { expectAssignable, expectError, expectType } from 'tsd';

interface Child {
name: string;
Expand Down Expand Up @@ -151,4 +151,34 @@ function gh11321(): void {
return 'foo';
}
});
}

function gh11503() {
interface Friend {
blocked: boolean
}
const FriendSchema = new Schema<Friend>({
blocked: Boolean
});

interface User {
friends: Types.ObjectId[];
}
const UserSchema = new Schema<User>({
friends: [{ type: Schema.Types.ObjectId, ref: 'friends' }]
});
const Users = model<User>('friends', UserSchema);

Users.findOne({}).populate('friends').then(user => {
expectType<Types.ObjectId | undefined>(user?.friends[0]);
expectError(user?.friends[0].blocked);
expectError(user?.friends.map(friend => friend.blocked));
});

Users.findOne({}).populate<{friends: Friend[]}>('friends').then(user => {
expectAssignable<Friend>(user?.friends[0]);
expectType<boolean>(user?.friends[0].blocked);
const firstFriendBlockedValue = user?.friends.map(friend => friend)[0];
expectType<boolean>(firstFriendBlockedValue?.blocked);
});
}
11 changes: 7 additions & 4 deletions types/index.d.ts
Expand Up @@ -1576,8 +1576,11 @@ declare module 'mongoose' {

type QueryWithHelpers<ResultType, DocType, THelpers = {}, RawDocType = DocType> = Query<ResultType, DocType, THelpers, RawDocType> & THelpers;

type UnpackedIntersection<T, U> = T extends (infer V)[] ? (V & U)[] : T & U;
type UnpackedIntersectionWithNull<T, U> = T extends null ? UnpackedIntersection<T, U> | null : UnpackedIntersection<T, U>;
type UnpackedIntersection<T, U> = T extends (infer A)[]
? (Omit<A, keyof U> & U)[]
: keyof U extends never
? T
: Omit<T, keyof U> & U;

type ProjectionFields<DocType> = {[Key in keyof Omit<LeanDocument<DocType>, '__v'>]?: any} & Record<string, any>;

Expand Down Expand Up @@ -1878,8 +1881,8 @@ declare module 'mongoose' {
polygon(path: string, ...coordinatePairs: number[][]): this;

/** Specifies paths which should be populated with other documents. */
populate<Paths = {}>(path: string | string[], select?: string | any, model?: string | Model<any, THelpers>, match?: any): QueryWithHelpers<UnpackedIntersectionWithNull<ResultType, Paths>, DocType, THelpers, RawDocType>;
populate<Paths = {}>(options: PopulateOptions | (PopulateOptions | string)[]): QueryWithHelpers<UnpackedIntersectionWithNull<ResultType, Paths>, DocType, THelpers, RawDocType>;
populate<Paths = {}>(path: string[], select?: string | any, model?: string | Model<any, THelpers>, match?: any): QueryWithHelpers<UnpackedIntersection<ResultType, Paths>, DocType, THelpers, RawDocType>;
populate<Paths = {}>(options: PopulateOptions | (PopulateOptions | string)[]): QueryWithHelpers<UnpackedIntersection<ResultType, Paths>, DocType, THelpers, RawDocType>;

/** Get/set the current projection (AKA fields). Pass `null` to remove the current projection. */
projection(): ProjectionFields<DocType> | null;
Expand Down

0 comments on commit 7ce083d

Please sign in to comment.