From 195103cec3aad94830f7f341387538d11e1dd06b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 Jul 2024 14:32:43 -0400 Subject: [PATCH 1/3] types: allow calling `SchemaType.cast()` without `parent` and `init` parameters Fix #14718 Re: #9076 --- test/schema.test.js | 20 ++++++++++++++++++++ test/types/schema.test.ts | 15 +++++++++++++++ types/schematypes.d.ts | 3 ++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/test/schema.test.js b/test/schema.test.js index 8cd58ba7b9f..3076c9df62a 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -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); + }); }); diff --git a/test/types/schema.test.ts b/test/types/schema.test.ts index 9dab60d2022..e3771e0dd64 100644 --- a/test/types/schema.test.ts +++ b/test/types/schema.test.ts @@ -1,5 +1,6 @@ import { DefaultSchemaOptions, + HydratedArraySubdocument, HydratedSingleSubdocument, Schema, Document, @@ -1555,3 +1556,17 @@ function gh14696() { }); } + +function gh14748() { + const nestedSchema = new Schema({ name: String }); + + const schema = new Schema({ + arr: [nestedSchema], + singleNested: nestedSchema + }); + + // Cast to single nested subdoc + const subdoc = schema.path('singleNested') + .cast>({ name: 'bar' }); + expectAssignable<{ name: string }>(subdoc); +} \ No newline at end of file diff --git a/types/schematypes.d.ts b/types/schematypes.d.ts index b7f1fc733b9..26eab700a81 100644 --- a/types/schematypes.d.ts +++ b/types/schematypes.d.ts @@ -220,7 +220,8 @@ declare module 'mongoose' { OptionsConstructor: SchemaTypeOptions; /** Cast `val` to this schema type. Each class that inherits from schema type should implement this function. */ - cast(val: any, doc: Document, init: boolean, prev?: any, options?: any): any; + cast(val: any, doc?: Document, init?: boolean, prev?: any, options?: any): any; + cast(val: any, doc?: Document, init?: boolean, prev?: any, options?: any): ResultType; /** Sets a default value for this SchemaType. */ default(val: any): any; From 9da1804fed1102a709c820186c3946cd9acaa80b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 23 Jul 2024 12:29:00 -0400 Subject: [PATCH 2/3] Update test/types/schema.test.ts Co-authored-by: hasezoey --- test/types/schema.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/types/schema.test.ts b/test/types/schema.test.ts index e3771e0dd64..b672d14e27e 100644 --- a/test/types/schema.test.ts +++ b/test/types/schema.test.ts @@ -1569,4 +1569,4 @@ function gh14748() { const subdoc = schema.path('singleNested') .cast>({ name: 'bar' }); expectAssignable<{ name: string }>(subdoc); -} \ No newline at end of file +} From 351b28957871cb371da10204b0986efa2f49d915 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 23 Jul 2024 12:37:55 -0400 Subject: [PATCH 3/3] types: improve return value for Types.Subdocument.cast() --- test/types/schema.test.ts | 7 ++++++- types/schematypes.d.ts | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/test/types/schema.test.ts b/test/types/schema.test.ts index b672d14e27e..a9679c082b8 100644 --- a/test/types/schema.test.ts +++ b/test/types/schema.test.ts @@ -1565,8 +1565,13 @@ function gh14748() { singleNested: nestedSchema }); - // Cast to single nested subdoc const subdoc = schema.path('singleNested') .cast>({ name: 'bar' }); expectAssignable<{ name: string }>(subdoc); + + const subdoc2 = schema.path('singleNested').cast({ name: 'bar' }); + expectAssignable<{ name: string }>(subdoc2); + + const subdoc3 = schema.path>('singleNested').cast({ name: 'bar' }); + expectAssignable<{ name: string }>(subdoc3); } diff --git a/types/schematypes.d.ts b/types/schematypes.d.ts index 26eab700a81..e8a0ecffdf0 100644 --- a/types/schematypes.d.ts +++ b/types/schematypes.d.ts @@ -444,7 +444,7 @@ declare module 'mongoose' { defaultOptions: Record; } - class Subdocument extends SchemaType implements AcceptsDiscriminator { + class Subdocument extends SchemaType implements AcceptsDiscriminator { /** This schema type's name, to defend against minifiers that mangle function names. */ static schemaName: string; @@ -456,6 +456,8 @@ declare module 'mongoose' { discriminator(name: string | number, schema: Schema, value?: string): U; discriminator(name: string | number, schema: Schema, value?: string): Model; + + cast(val: any, doc?: Document, init?: boolean, prev?: any, options?: any): HydratedSingleSubdocument; } class String extends SchemaType {