From 05e007b0b5ff98151c3ff972ee2f881b4203639e Mon Sep 17 00:00:00 2001 From: Eliott C Date: Wed, 20 Jul 2022 20:15:18 +0200 Subject: [PATCH] fix(NODE-4423): better type support for nested objects in query & update (#3328) --- src/mongo_types.ts | 2 +- .../community/collection/filterQuery.test-d.ts | 3 +++ .../types/community/collection/updateX.test-d.ts | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/mongo_types.ts b/src/mongo_types.ts index 9891e0abf5..124e9ce9e3 100644 --- a/src/mongo_types.ts +++ b/src/mongo_types.ts @@ -531,7 +531,7 @@ export type NestedPaths = Type extends : // child is an array, but it's not a recursive array [Key, ...NestedPaths] : // child is not structured the same as the parent - [Key, ...NestedPaths]; + [Key, ...NestedPaths] | [Key]; }[Extract] : []; diff --git a/test/types/community/collection/filterQuery.test-d.ts b/test/types/community/collection/filterQuery.test-d.ts index 2f4d7f7e53..dd17868514 100644 --- a/test/types/community/collection/filterQuery.test-d.ts +++ b/test/types/community/collection/filterQuery.test-d.ts @@ -178,6 +178,7 @@ expectNotType>({ 'regex.dotAll': true }); collectionT.find({ 'meta.updatedAt': new Date() }); collectionT.find({ 'meta.deep.nested.level': 123 }); collectionT.find({ meta: { deep: { nested: { level: 123 } } } }); // no impact on actual nesting +collectionT.find({ 'meta.deep': { nested: { level: 123 } } }); collectionT.find({ 'friends.0.name': 'John' }); collectionT.find({ 'playmates.0.name': 'John' }); // supports arrays with primitive types @@ -203,6 +204,8 @@ expectNotType>({ 'friends.0.name': 123 }); expectNotType>({ 'playmates.0.name': 123 }); expectNotType>({ 'laps.foo': 'string' }); expectNotType>({ 'treats.0': 123 }); +expectNotType>({ meta: { deep: { nested: { level: 'string' } } } }); +expectNotType>({ 'meta.deep': { nested: { level: 'string' } } }); /// it should not accept wrong types for nested document array fields expectError>({ diff --git a/test/types/community/collection/updateX.test-d.ts b/test/types/community/collection/updateX.test-d.ts index 6d269bc320..01b7ccfc6e 100644 --- a/test/types/community/collection/updateX.test-d.ts +++ b/test/types/community/collection/updateX.test-d.ts @@ -74,6 +74,10 @@ interface SubTestModel { field1: string; field2?: string; field3?: number; + nestedObject?: { + a: string; + b: string; + }; } type FruitTypes = 'apple' | 'pear'; @@ -97,6 +101,7 @@ interface TestModel { subInterfaceField: SubTestModel; subInterfaceArray: SubTestModel[]; timestampField: Timestamp; + extras: Record; } const collectionTType = db.collection('test.update'); @@ -201,9 +206,20 @@ expectAssignable>({ expectAssignable>({ $set: { doubleField: new Double(1.23) } }); expectAssignable>({ $set: { int32Field: new Int32(10) } }); expectAssignable>({ $set: { longField: Long.fromString('999') } }); +expectAssignable>({ $set: { extras: { someExtras: { id: 'someId' } } } }); expectAssignable>({ $set: { stringField: 'a' } }); expectError(buildUpdateFilter({ $set: { stringField: 123 } })); expectAssignable>({ $set: { 'subInterfaceField.field2': '2' } }); +expectAssignable>({ $set: { 'subInterfaceField.nestedObject.a': '2' } }); +expectAssignable>({ + $set: { 'subInterfaceField.nestedObject': { a: '1', b: '2' } } +}); +expectError>({ + $set: { 'subInterfaceField.nestedObject': { a: '1' } } +}); +expectError>({ + $set: { 'subInterfaceField.nestedObject': { a: 1, b: '2' } } +}); expectError(buildUpdateFilter({ $set: { 'subInterfaceField.field2': 2 } })); expectError(buildUpdateFilter({ $set: { 'unknown.field': null } })); expectAssignable>({ $set: { 'numberArray.$': 40 } });