Skip to content

Commit

Permalink
types: make Buffers into mongodb.Binary in lean result type to match …
Browse files Browse the repository at this point in the history
…runtime behavior

Fix #14902
  • Loading branch information
vkarpov15 committed Oct 16, 2024
1 parent 0752c5d commit 8825b76
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 4 deletions.
17 changes: 15 additions & 2 deletions test/types/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import {
Types,
Query,
model,
ValidateOpts
ValidateOpts,
BufferToBinary
} from 'mongoose';
import { Binary } from 'mongodb';
import { IsPathRequired } from '../../types/inferschematype';
import { expectType, expectError, expectAssignable } from 'tsd';
import { ObtainDocumentPathType, ResolvePathType } from '../../types/inferschematype';
Expand Down Expand Up @@ -917,7 +919,7 @@ async function gh12593() {
expectType<Buffer | undefined | null>(doc2.x);

const doc3 = await Test.findOne({}).orFail().lean();
expectType<Buffer | undefined | null>(doc3.x);
expectType<Binary | undefined | null>(doc3.x);

const arrSchema = new Schema({ arr: [{ type: Schema.Types.UUID }] });

Expand Down Expand Up @@ -1663,3 +1665,14 @@ async function gh14950() {
expectType<string>(doc.location!.type);
expectType<number[]>(doc.location!.coordinates);
}

async function gh14902() {
const def = {
image: { type: Buffer }
} as const;
const exampleSchema = new Schema(def);
const Test = model('Test', exampleSchema);

const doc = await Test.findOne().lean().orFail();
expectType<Binary | null | undefined>(doc.image);
}
10 changes: 9 additions & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,14 @@ declare module 'mongoose' {
[K in keyof T]: FlattenProperty<T[K]>;
};

export type BufferToBinary<T> = T extends object ? {
[K in keyof T]: T[K] extends Buffer
? mongodb.Binary
: T[K] extends (Buffer | null | undefined)
? mongodb.Binary | null | undefined
: T[K];
} : T;

/**
* Separate type is needed for properties of union type (for example, Types.DocumentArray | undefined) to apply conditional check to each member of it
* https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types
Expand All @@ -716,7 +724,7 @@ declare module 'mongoose' {
? Types.DocumentArray<FlattenMaps<ItemType>> : FlattenMaps<T>;

export type actualPrimitives = string | boolean | number | bigint | symbol | null | undefined;
export type TreatAsPrimitives = actualPrimitives | NativeDate | RegExp | symbol | Error | BigInt | Types.ObjectId | Buffer | Function;
export type TreatAsPrimitives = actualPrimitives | NativeDate | RegExp | symbol | Error | BigInt | Types.ObjectId | Buffer | Function | mongodb.Binary;

export type SchemaDefinitionType<T> = T extends Document ? Omit<T, Exclude<keyof Document, '_id' | 'id' | '__v'>> : T;

Expand Down
2 changes: 1 addition & 1 deletion types/query.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ declare module 'mongoose' {
type QueryOpThatReturnsDocument = 'find' | 'findOne' | 'findOneAndUpdate' | 'findOneAndReplace' | 'findOneAndDelete';

type GetLeanResultType<RawDocType, ResultType, QueryOp> = QueryOp extends QueryOpThatReturnsDocument
? (ResultType extends any[] ? Require_id<FlattenMaps<RawDocType>>[] : Require_id<FlattenMaps<RawDocType>>)
? (ResultType extends any[] ? Require_id<FlattenMaps<BufferToBinary<RawDocType>>>[] : Require_id<FlattenMaps<BufferToBinary<RawDocType>>>)
: ResultType;

type MergePopulatePaths<RawDocType, ResultType, QueryOp, Paths, TQueryHelpers, TInstanceMethods = Record<string, never>> = QueryOp extends QueryOpThatReturnsDocument
Expand Down

0 comments on commit 8825b76

Please sign in to comment.