Skip to content
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

types: allow calling SchemaType.cast() without parent and init parameters #14756

Merged
merged 3 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions test/schema.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3258,4 +3258,24 @@ describe('schema', function() {

await q;
});

it('supports casting object to subdocument (gh-14748) (gh-9076)', function() {
const nestedSchema = new Schema({ name: String });
nestedSchema.methods.getAnswer = () => 42;

const schema = new Schema({
arr: [nestedSchema],
singleNested: nestedSchema
});

// Cast to doc array
let subdoc = schema.path('arr').cast([{ name: 'foo' }])[0];
assert.ok(subdoc instanceof mongoose.Document);
assert.equal(subdoc.getAnswer(), 42);

// Cast to single nested subdoc
subdoc = schema.path('singleNested').cast({ name: 'bar' });
assert.ok(subdoc instanceof mongoose.Document);
assert.equal(subdoc.getAnswer(), 42);
});
});
20 changes: 20 additions & 0 deletions test/types/schema.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
DefaultSchemaOptions,
HydratedArraySubdocument,
HydratedSingleSubdocument,
Schema,
Document,
Expand Down Expand Up @@ -1555,3 +1556,22 @@ function gh14696() {
});

}

function gh14748() {
const nestedSchema = new Schema({ name: String });

const schema = new Schema({
arr: [nestedSchema],
singleNested: nestedSchema
});

const subdoc = schema.path('singleNested')
.cast<HydratedArraySubdocument<{ name: string }>>({ name: 'bar' });
expectAssignable<{ name: string }>(subdoc);
vkarpov15 marked this conversation as resolved.
Show resolved Hide resolved

const subdoc2 = schema.path('singleNested').cast({ name: 'bar' });
expectAssignable<{ name: string }>(subdoc2);

const subdoc3 = schema.path<Schema.Types.Subdocument<{ name: string }>>('singleNested').cast({ name: 'bar' });
expectAssignable<{ name: string }>(subdoc3);
}
7 changes: 5 additions & 2 deletions types/schematypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ declare module 'mongoose' {
OptionsConstructor: SchemaTypeOptions<T>;

/** Cast `val` to this schema type. Each class that inherits from schema type should implement this function. */
cast(val: any, doc: Document<any>, init: boolean, prev?: any, options?: any): any;
cast(val: any, doc?: Document<any>, init?: boolean, prev?: any, options?: any): any;
cast<ResultType>(val: any, doc?: Document<any>, init?: boolean, prev?: any, options?: any): ResultType;

/** Sets a default value for this SchemaType. */
default(val: any): any;
Expand Down Expand Up @@ -443,7 +444,7 @@ declare module 'mongoose' {
defaultOptions: Record<string, any>;
}

class Subdocument extends SchemaType implements AcceptsDiscriminator {
class Subdocument<DocType = unknown> extends SchemaType implements AcceptsDiscriminator {
/** This schema type's name, to defend against minifiers that mangle function names. */
static schemaName: string;

Expand All @@ -455,6 +456,8 @@ declare module 'mongoose' {

discriminator<T, U>(name: string | number, schema: Schema<T, U>, value?: string): U;
discriminator<D>(name: string | number, schema: Schema, value?: string): Model<D>;

cast(val: any, doc?: Document<any>, init?: boolean, prev?: any, options?: any): HydratedSingleSubdocument<DocType>;
}

class String extends SchemaType {
Expand Down