Skip to content

Commit

Permalink
fix(index.d.ts): avoid UnpackedIntersection making `findOne().populat…
Browse files Browse the repository at this point in the history
…e()` result non-nullable

Fix #11041
  • Loading branch information
vkarpov15 committed Jan 23, 2022
1 parent 6c9a9ca commit c530400
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 3 deletions.
5 changes: 3 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2124,6 +2124,7 @@ 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>;

class Query<ResultType, DocType, THelpers = {}, RawDocType = DocType> {
_mongooseOptions: MongooseQueryOptions;
Expand Down Expand Up @@ -2407,8 +2408,8 @@ declare module 'mongoose' {
polygon(path: string, ...coordinatePairs: number[][]): this;

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

/** Get/set the current projection (AKA fields). Pass `null` to remove the current projection. */
projection(fields?: any | null): this;
Expand Down
3 changes: 2 additions & 1 deletion test/typescript/main.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ describe('typescript syntax', function() {
it('queries', function() {
const errors = runTest('queries.ts', { strict: true });
printTSErrors(errors);
assert.equal(errors.length, 1);
assert.equal(errors.length, 2);
assert.ok(errors[0].messageText.includes('notAQueryHelper'), errors[0].messageText);
assert.ok(errors[1].messageText.messageText.includes('| null\' is not assignable'), errors[0].messageText);
});

it('create', function() {
Expand Down
20 changes: 20 additions & 0 deletions test/typescript/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,4 +184,24 @@ function gh10786() {
if (true) {
updateQuery.phone = 'XXXX';
}
}

async function gh11041(): Promise<void> {
interface User {
name: string;
email: string;
avatar?: string;
}

// 2. Create a Schema corresponding to the document interface.
const schema = new Schema<User>({
name: { type: String, required: true },
email: { type: String, required: true },
avatar: String
});

// 3. Create a Model.
const MyModel = model<User>('User', schema);

const maybeDoc3: { _id: Types.ObjectId } = await MyModel.findOne({}).populate('someField').exec();
}

0 comments on commit c530400

Please sign in to comment.