Skip to content

Commit

Permalink
test(NODE-4498): ts tests for OptionalId wrapping schemas with _id (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
dariakp committed Dec 15, 2022
1 parent e3ead58 commit d56414f
Showing 1 changed file with 101 additions and 5 deletions.
106 changes: 101 additions & 5 deletions test/types/schema_helpers.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Document, ObjectId } from 'bson';
import { expectAssignable, expectError, expectNotType, expectType } from 'tsd';

import type { Collection } from '../../src';
import type {
EnhancedOmit,
InferIdType,
Expand All @@ -10,7 +11,10 @@ import type {
WithoutId
} from '../../src/mongo_types';

// InferIdType
/** ----------------------------------------------------------------------
* InferIdType
*/

expectType<InferIdType<Document>>(new ObjectId());
expectType<InferIdType<{ _id: number }>>(1 + 1);
expectType<InferIdType<{ a: number } | { b: string }>>(new ObjectId());
Expand All @@ -22,13 +26,20 @@ expectError<InferIdType<{ _id: Record<string, any> }>>({});
expectAssignable<InferIdType<{ _id: number } | { b: string }>>(new ObjectId());
expectAssignable<InferIdType<{ _id: number } | { b: string }>>(1 + 1);

// WithId
/** ----------------------------------------------------------------------
* WithId
*/

expectAssignable<WithId<Document>>({ _id: new ObjectId() });
expectAssignable<WithId<{ a: number }>>({ _id: new ObjectId(), a: 3 });
expectAssignable<WithId<{ _id: ObjectId }>>({ _id: new ObjectId() });
expectAssignable<WithId<{ _id: number }>>({ _id: 5 });
expectNotType<WithId<Document>>({ _id: 3 });

/** ----------------------------------------------------------------------
* OptionalId
*/

// Changing _id to a type other than ObjectId makes it required:
expectNotType<OptionalId<{ _id: number; a: number }>>({ a: 3 });
expectNotType<OptionalId<{ _id: number; a: number } | { _id: ObjectId; b: number }>>({ a: 3 });
Expand All @@ -44,20 +55,105 @@ class MyId {}
expectNotType<OptionalId<{ _id: MyId; a: number }>>({ a: 3 });
expectNotType<OptionalId<{ _id: MyId; a: number }>>({ _id: new ObjectId(), a: 3 });

// OptionalId assignability when wrapping a schema with _id: ObjectId
type SchemaWithIdType = {
_id: ObjectId;
a: number;
};
interface SchemaWithIdInterface {
_id: ObjectId;
a: number;
}
declare const typeTestCollection: Collection<OptionalId<SchemaWithIdType>>;
declare const interfaceTestCollection: Collection<OptionalId<SchemaWithIdInterface>>;

expectAssignable<SchemaWithIdType | null>(await typeTestCollection.findOne());
expectAssignable<SchemaWithIdInterface | null>(await interfaceTestCollection.findOne());
expectAssignable<SchemaWithIdType>((await typeTestCollection.find().toArray())[0]);
expectAssignable<SchemaWithIdInterface>((await interfaceTestCollection.find().toArray())[0]);
expectAssignable<SchemaWithIdType | null>(
(await typeTestCollection.findOneAndDelete({ a: 1 })).value
);
expectAssignable<SchemaWithIdInterface | null>(
(await interfaceTestCollection.findOneAndDelete({ a: 1 })).value
);
expectAssignable<SchemaWithIdType | null>(
(await typeTestCollection.findOneAndReplace({ a: 1 }, { a: 5 })).value
);
expectAssignable<SchemaWithIdInterface | null>(
(await interfaceTestCollection.findOneAndReplace({ a: 1 }, { a: 5 })).value
);
expectAssignable<SchemaWithIdType | null>(
(await typeTestCollection.findOneAndUpdate({ a: 1 }, { a: 5 })).value
);
expectAssignable<SchemaWithIdInterface | null>(
(await interfaceTestCollection.findOneAndUpdate({ a: 1 }, { a: 5 })).value
);

// OptionalId assignability when wrapping a schema with _id: number
type SchemaWithIdNumberType = {
_id: number;
a: number;
};
interface SchemaWithIdNumberInterface {
_id: number;
a: number;
}
declare const typeNumberTestCollection: Collection<OptionalId<SchemaWithIdNumberType>>;
declare const interfaceNumberTestCollection: Collection<OptionalId<SchemaWithIdNumberInterface>>;

expectAssignable<SchemaWithIdNumberType | null>(await typeNumberTestCollection.findOne());
expectAssignable<SchemaWithIdNumberInterface | null>(await interfaceNumberTestCollection.findOne());
expectAssignable<SchemaWithIdNumberType>((await typeNumberTestCollection.find().toArray())[0]);
expectAssignable<SchemaWithIdNumberInterface>(
(await interfaceNumberTestCollection.find().toArray())[0]
);
expectAssignable<SchemaWithIdNumberType | null>(
(await typeNumberTestCollection.findOneAndDelete({ a: 1 })).value
);
expectAssignable<SchemaWithIdNumberInterface | null>(
(await interfaceNumberTestCollection.findOneAndDelete({ a: 1 })).value
);
expectAssignable<SchemaWithIdNumberType | null>(
(await typeNumberTestCollection.findOneAndReplace({ a: 1 }, { a: 5 })).value
);
expectAssignable<SchemaWithIdNumberInterface | null>(
(await interfaceNumberTestCollection.findOneAndReplace({ a: 1 }, { a: 5 })).value
);
expectAssignable<SchemaWithIdNumberType | null>(
(await typeNumberTestCollection.findOneAndUpdate({ a: 1 }, { a: 5 })).value
);
expectAssignable<SchemaWithIdNumberInterface | null>(
(await interfaceNumberTestCollection.findOneAndUpdate({ a: 1 }, { a: 5 })).value
);

/** ----------------------------------------------------------------------
* OptionalUnlessRequiredId
*/

declare function functionReturningOptionalId(): OptionalId<{
_id?: ObjectId | undefined;
a: number;
}>;
// OptionalUnlessRequiredId
expectType<OptionalUnlessRequiredId<{ _id: ObjectId; a: number }>>({ a: 3, _id: new ObjectId() });
expectType<OptionalUnlessRequiredId<{ _id?: ObjectId; a: number }>>(functionReturningOptionalId());

// WithoutId removes _id whether defined in the schema or not
/** ----------------------------------------------------------------------
* WithoutId
*
* WithoutId removes _id whether defined in the schema or not
*/

expectType<WithoutId<{ _id: number; a: number }>>({ a: 2 });
expectNotType<WithoutId<{ _id: number; a: number }>>({ _id: 3, a: 2 });
expectNotType<WithoutId<{ a: number }>>({ _id: 3, a: 2 });

// EnhancedOmit fixes a problem with Typescript's built in Omit that breaks discriminated unions
/** ----------------------------------------------------------------------
* EnhancedOmit
*
* EnhancedOmit fixes a problem with Typescript's built in Omit that breaks discriminated unions
*/

// NODE-3287
// expectNotAssignable<EnhancedOmit<{ a: 'one' } | { b: 'two' }, 'a'>>({
// a: 'one' as const
Expand Down

0 comments on commit d56414f

Please sign in to comment.