Skip to content

Commit 05e007b

Browse files
authored
fix(NODE-4423): better type support for nested objects in query & update (#3328)
1 parent 7613d4b commit 05e007b

File tree

3 files changed

+20
-1
lines changed

3 files changed

+20
-1
lines changed

src/mongo_types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ export type NestedPaths<Type> = Type extends
531531
: // child is an array, but it's not a recursive array
532532
[Key, ...NestedPaths<Type[Key]>]
533533
: // child is not structured the same as the parent
534-
[Key, ...NestedPaths<Type[Key]>];
534+
[Key, ...NestedPaths<Type[Key]>] | [Key];
535535
}[Extract<keyof Type, string>]
536536
: [];
537537

test/types/community/collection/filterQuery.test-d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ expectNotType<Filter<PetModel>>({ 'regex.dotAll': true });
178178
collectionT.find({ 'meta.updatedAt': new Date() });
179179
collectionT.find({ 'meta.deep.nested.level': 123 });
180180
collectionT.find({ meta: { deep: { nested: { level: 123 } } } }); // no impact on actual nesting
181+
collectionT.find({ 'meta.deep': { nested: { level: 123 } } });
181182
collectionT.find({ 'friends.0.name': 'John' });
182183
collectionT.find({ 'playmates.0.name': 'John' });
183184
// supports arrays with primitive types
@@ -203,6 +204,8 @@ expectNotType<Filter<PetModel>>({ 'friends.0.name': 123 });
203204
expectNotType<Filter<PetModel>>({ 'playmates.0.name': 123 });
204205
expectNotType<Filter<PetModel>>({ 'laps.foo': 'string' });
205206
expectNotType<Filter<PetModel>>({ 'treats.0': 123 });
207+
expectNotType<Filter<PetModel>>({ meta: { deep: { nested: { level: 'string' } } } });
208+
expectNotType<Filter<PetModel>>({ 'meta.deep': { nested: { level: 'string' } } });
206209

207210
/// it should not accept wrong types for nested document array fields
208211
expectError<Filter<PetModel>>({

test/types/community/collection/updateX.test-d.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ interface SubTestModel {
7474
field1: string;
7575
field2?: string;
7676
field3?: number;
77+
nestedObject?: {
78+
a: string;
79+
b: string;
80+
};
7781
}
7882

7983
type FruitTypes = 'apple' | 'pear';
@@ -97,6 +101,7 @@ interface TestModel {
97101
subInterfaceField: SubTestModel;
98102
subInterfaceArray: SubTestModel[];
99103
timestampField: Timestamp;
104+
extras: Record<string, { id: string }>;
100105
}
101106
const collectionTType = db.collection<TestModel>('test.update');
102107

@@ -201,9 +206,20 @@ expectAssignable<UpdateFilter<TestModel>>({
201206
expectAssignable<UpdateFilter<TestModel>>({ $set: { doubleField: new Double(1.23) } });
202207
expectAssignable<UpdateFilter<TestModel>>({ $set: { int32Field: new Int32(10) } });
203208
expectAssignable<UpdateFilter<TestModel>>({ $set: { longField: Long.fromString('999') } });
209+
expectAssignable<UpdateFilter<TestModel>>({ $set: { extras: { someExtras: { id: 'someId' } } } });
204210
expectAssignable<UpdateFilter<TestModel>>({ $set: { stringField: 'a' } });
205211
expectError(buildUpdateFilter({ $set: { stringField: 123 } }));
206212
expectAssignable<UpdateFilter<TestModel>>({ $set: { 'subInterfaceField.field2': '2' } });
213+
expectAssignable<UpdateFilter<TestModel>>({ $set: { 'subInterfaceField.nestedObject.a': '2' } });
214+
expectAssignable<UpdateFilter<TestModel>>({
215+
$set: { 'subInterfaceField.nestedObject': { a: '1', b: '2' } }
216+
});
217+
expectError<UpdateFilter<TestModel>>({
218+
$set: { 'subInterfaceField.nestedObject': { a: '1' } }
219+
});
220+
expectError<UpdateFilter<TestModel>>({
221+
$set: { 'subInterfaceField.nestedObject': { a: 1, b: '2' } }
222+
});
207223
expectError(buildUpdateFilter({ $set: { 'subInterfaceField.field2': 2 } }));
208224
expectError(buildUpdateFilter({ $set: { 'unknown.field': null } }));
209225
expectAssignable<UpdateFilter<TestModel>>({ $set: { 'numberArray.$': 40 } });

0 commit comments

Comments
 (0)