Skip to content

Commit

Permalink
fix: support positional array operator
Browse files Browse the repository at this point in the history
The type-checking is not as strict as it could be
  • Loading branch information
coyotte508 committed May 23, 2022
1 parent e41089b commit f048e8e
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 8 deletions.
19 changes: 18 additions & 1 deletion src/mongo_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,24 @@ export type OnlyFieldsOfType<TSchema, FieldType = any, AssignableType = FieldTyp
/** @public */
export type MatchKeysAndValues<TSchema> = Readonly<{
[Property in Join<NestedPaths<TSchema>, '.'>]?: PropertyType<TSchema, Property>;
}>;
}> &
// Positional array update operator
Partial<
Record<
`${KeysOfAType<
{
[Property in Join<NestedPaths<TSchema>, '.'>]?: PropertyType<TSchema, Property>;
},
// Make sure the values for the keys are arrays
any[]
>}.$${`[${string}]` | ''}${
// Subsequent nested path - could be narrowed
`.${string}` | ''
}`,
// Value for updated field - could be narrowed
any
>
>;

/** @public */
export type AddToSetOperators<Type> = {
Expand Down
4 changes: 2 additions & 2 deletions test/types/community/collection/bulkWrite.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ collectionType.bulkWrite([
update: {
$set: {
numberField: 123,
'dot.notation': true
'subInterfaceField.field1': 'true'
}
}
}
Expand Down Expand Up @@ -123,7 +123,7 @@ collectionType.bulkWrite([
update: {
$set: {
numberField: 123,
'dot.notation': true
'subInterfaceField.field2': 'true'
}
}
}
Expand Down
13 changes: 8 additions & 5 deletions test/types/community/collection/updateX.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import type {
} from '../../../../src/mongo_types';

// MatchKeysAndValues - for basic mapping keys to their values, restricts that key types must be the same but optional, and permit dot array notation
expectAssignable<MatchKeysAndValues<{ a: number; b: string }>>({ a: 2, 'dot.notation': true });
expectAssignable<MatchKeysAndValues<{ a: number; b: string; c: { d: boolean } }>>({
a: 2,
'c.d': true
});
expectNotType<MatchKeysAndValues<{ a: number; b: string }>>({ b: 2 });

// AddToSetOperators
Expand Down Expand Up @@ -148,7 +151,7 @@ expectAssignable<UpdateFilter<TestModel>>({ $min: { doubleField: new Double(1.23
expectAssignable<UpdateFilter<TestModel>>({ $min: { int32Field: new Int32(10) } });
expectAssignable<UpdateFilter<TestModel>>({ $min: { longField: Long.fromString('999') } });
expectAssignable<UpdateFilter<TestModel>>({ $min: { stringField: 'a' } });
expectAssignable<UpdateFilter<TestModel>>({ $min: { 'dot.notation': 2 } });
expectAssignable<UpdateFilter<TestModel>>({ $min: { 'subInterfaceField.field1': '2' } });
expectAssignable<UpdateFilter<TestModel>>({ $min: { 'subInterfaceArray.$': 'string' } });
expectAssignable<UpdateFilter<TestModel>>({ $min: { 'subInterfaceArray.$[bla]': 40 } });
expectAssignable<UpdateFilter<TestModel>>({ $min: { 'subInterfaceArray.$[]': 1000.2 } });
Expand All @@ -163,7 +166,7 @@ expectAssignable<UpdateFilter<TestModel>>({ $max: { doubleField: new Double(1.23
expectAssignable<UpdateFilter<TestModel>>({ $max: { int32Field: new Int32(10) } });
expectAssignable<UpdateFilter<TestModel>>({ $max: { longField: Long.fromString('999') } });
expectAssignable<UpdateFilter<TestModel>>({ $max: { stringField: 'a' } });
expectAssignable<UpdateFilter<TestModel>>({ $max: { 'dot.notation': 2 } });
expectAssignable<UpdateFilter<TestModel>>({ $max: { 'subInterfaceField.field1': '2' } });
expectAssignable<UpdateFilter<TestModel>>({ $max: { 'subInterfaceArray.$': -10 } });
expectAssignable<UpdateFilter<TestModel>>({ $max: { 'subInterfaceArray.$[bla]': 40 } });
expectAssignable<UpdateFilter<TestModel>>({ $max: { 'subInterfaceArray.$[]': 1000.2 } });
Expand Down Expand Up @@ -192,7 +195,7 @@ expectAssignable<UpdateFilter<TestModel>>({ $set: { int32Field: new Int32(10) }
expectAssignable<UpdateFilter<TestModel>>({ $set: { longField: Long.fromString('999') } });
expectAssignable<UpdateFilter<TestModel>>({ $set: { stringField: 'a' } });
expectError(buildUpdateFilter({ $set: { stringField: 123 } }));
expectAssignable<UpdateFilter<TestModel>>({ $set: { 'dot.notation': 2 } });
expectAssignable<UpdateFilter<TestModel>>({ $set: { 'subInterfaceField.field2': '2' } });
expectAssignable<UpdateFilter<TestModel>>({ $set: { 'subInterfaceArray.$': -10 } });
expectAssignable<UpdateFilter<TestModel>>({ $set: { 'subInterfaceArray.$[bla]': 40 } });
expectAssignable<UpdateFilter<TestModel>>({ $set: { 'subInterfaceArray.$[]': 1000.2 } });
Expand All @@ -206,7 +209,7 @@ expectAssignable<UpdateFilter<TestModel>>({ $setOnInsert: { int32Field: new Int3
expectAssignable<UpdateFilter<TestModel>>({ $setOnInsert: { longField: Long.fromString('999') } });
expectAssignable<UpdateFilter<TestModel>>({ $setOnInsert: { stringField: 'a' } });
expectError(buildUpdateFilter({ $setOnInsert: { stringField: 123 } }));
expectAssignable<UpdateFilter<TestModel>>({ $setOnInsert: { 'dot.notation': 2 } });
expectAssignable<UpdateFilter<TestModel>>({ $setOnInsert: { 'subInterfaceField.field1': '2' } });
expectAssignable<UpdateFilter<TestModel>>({ $setOnInsert: { 'subInterfaceArray.$': -10 } });
expectAssignable<UpdateFilter<TestModel>>({ $setOnInsert: { 'subInterfaceArray.$[bla]': 40 } });
expectAssignable<UpdateFilter<TestModel>>({ $setOnInsert: { 'subInterfaceArray.$[]': 1000.2 } });
Expand Down

0 comments on commit f048e8e

Please sign in to comment.