Skip to content

Commit e138f8f

Browse files
committed
Add TypeScript error when filtering on field not in schema
As a developer, I'd like the type system to catch errors I make, like trying to query on a field that doesn't exist, or when I have made a typo in an existing field name. Previously, querying for these fields outside the schema would pass type checks because the `Filter<TSchema>` type included a union with `RootFilterOperators<WithId<TSchema>>`, and `RootFilterOperators` was defined as `extends Document`. The BSON `Document` type itself is an object with the index property `{ [key: string]: any }`, meaning that it would match documents with any keys! So, while our type checks would give us an error if we tried to pass the wrong type into a filter expression, trying to use an unknown field name would instead compare the value to the `any` type. By removing the `extends Document` clause of the `RootFilterOperators` type definition, we get much stronger guarantees from the `Filter` type.
1 parent e61a741 commit e138f8f

File tree

2 files changed

+11
-4
lines changed

2 files changed

+11
-4
lines changed

src/mongo_types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export type AlternativeType<T> = T extends ReadonlyArray<infer U>
9090
export type RegExpOrString<T> = T extends string ? BSONRegExp | RegExp | T : T;
9191

9292
/** @public */
93-
export interface RootFilterOperators<TSchema> extends Document {
93+
export interface RootFilterOperators<TSchema> {
9494
$and?: Filter<TSchema>[];
9595
$nor?: Filter<TSchema>[];
9696
$or?: Filter<TSchema>[];

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ expectType<WithId<PetModel>[]>(
126126
expectType<WithId<PetModel>[]>(
127127
await collectionT.find({ name: new BSONRegExp('MrMeow', 'i') }).toArray()
128128
);
129+
130+
/// it should not accept fields that are not in the schema
131+
type FT = Filter<PetModel>;
132+
expectNotType<FT>({ missing: true });
133+
129134
/// it should not accept wrong types for string fields
130135
expectNotType<Filter<PetModel>>({ name: 23 });
131136
expectNotType<Filter<PetModel>>({ name: { suffix: 'Jr' } });
@@ -361,9 +366,11 @@ expectError(
361366
otherField: new ObjectId()
362367
})
363368
);
364-
nonObjectIdCollection.find({
365-
fieldThatDoesNotExistOnSchema: new ObjectId()
366-
});
369+
expectError(
370+
nonObjectIdCollection.find({
371+
fieldThatDoesNotExistOnSchema: new ObjectId()
372+
})
373+
);
367374

368375
// we only forbid objects that "look like" object ids, so other random objects are permitted
369376
nonObjectIdCollection.find({

0 commit comments

Comments
 (0)