Skip to content

Commit

Permalink
Add extra property to DefaultSchemaOptions and refactor the related t…
Browse files Browse the repository at this point in the history
…ests.
  • Loading branch information
mohammad0-0ahmad committed Jul 21, 2022
1 parent efb11ea commit d487695
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 31 deletions.
14 changes: 6 additions & 8 deletions test/types/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
Query,
HydratedDocument,
SchemaOptions,
ObtainSchemaGeneric
ObtainSchemaGeneric,
DefaultSchemaOptions,
FlatRecord
} from 'mongoose';
import { expectType, expectError, expectAssignable } from 'tsd';

Expand Down Expand Up @@ -692,14 +694,10 @@ function gh12030() {

function gh12122() {
const Test1 = new Schema({ test: String }, { typeKey: 'customTypeKey' });
expectType<{
expectType<FlatRecord<Omit<DefaultSchemaOptions, 'typeKey'> & {
typeKey: 'customTypeKey';
id: true;
}>({} as ObtainSchemaGeneric<typeof Test1, 'TSchemaOptions'>);
}>>({} as ObtainSchemaGeneric<typeof Test1, 'TSchemaOptions'>);

const Test2 = new Schema({ test: String }, {});
expectType<{
typeKey: 'type';
id: true;
}>({} as ObtainSchemaGeneric<typeof Test2, 'TSchemaOptions'>);
expectType<DefaultSchemaOptions>({} as ObtainSchemaGeneric<typeof Test2, 'TSchemaOptions'>);
}
28 changes: 16 additions & 12 deletions types/inferschematype.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ import {
InferSchemaType,
SchemaType,
SchemaTypeOptions,
TypeKeyBaseType,
Types,
NumberSchemaDefinition,
StringSchemaDefinition,
BooleanSchemaDefinition,
DateSchemaDefinition,
ObtainDocumentType,
DefaultTypeKey,
ObjectIdSchemaDefinition,
IfEquals
IfEquals,
SchemaOptions,
DefaultSchemaOptions
} from 'mongoose';

declare module 'mongoose' {
Expand All @@ -21,7 +21,7 @@ declare module 'mongoose' {
* @description Obtains document schema type from document Definition OR returns enforced schema type if it's provided.
* @param {DocDefinition} DocDefinition A generic equals to the type of document definition "provided in as first parameter in Schema constructor".
* @param {EnforcedDocType} EnforcedDocType A generic type enforced by user "provided before schema constructor".
* @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
* @param {TSchemaOptions} TSchemaOptions A generic represent the type of schema options.
*/
type ObtainDocumentType<DocDefinition, EnforcedDocType = any, TSchemaOptions extends Record<any, any> = DefaultSchemaOptions> =
IsItRecordAndNotAny<EnforcedDocType> extends true ? EnforcedDocType : {
Expand Down Expand Up @@ -59,6 +59,10 @@ declare module 'mongoose' {
}[alias]
: unknown;

/**
* @summary Helper to obtain and resolve the schema options which are has an effect on schema type.
* @param {T} T Schema option to be resolved.
*/
type ResolveSchemaOptions<T> = Omit<MergeType<DefaultSchemaOptions, T>, 'statics' | 'methods' | 'query' | 'virtuals'>;
}

Expand All @@ -68,7 +72,7 @@ declare module 'mongoose' {
* @param {P} P Document path.
* @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
*/
type IsPathRequired<P, TypeKey extends TypeKeyBaseType> =
type IsPathRequired<P, TypeKey extends string> =
P extends { required: true | [true, string | undefined] } | ArrayConstructor | any[]
? true
: P extends (Record<TypeKey, ArrayConstructor | any[]>)
Expand All @@ -86,15 +90,15 @@ type IsPathRequired<P, TypeKey extends TypeKeyBaseType> =
* @description It helps to check if a path is defined by TypeKey OR not.
* @param {TypeKey} TypeKey A literal string refers to path type property key.
*/
type PathWithTypePropertyBaseType<TypeKey extends TypeKeyBaseType> = { [k in TypeKey]: any };
type PathWithTypePropertyBaseType<TypeKey extends string> = { [k in TypeKey]: any };

/**
* @summary A Utility to obtain schema's required path keys.
* @param {T} T A generic refers to document definition.
* @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
* @returns required paths keys of document definition.
*/
type RequiredPathKeys<T, TypeKey extends TypeKeyBaseType> = {
type RequiredPathKeys<T, TypeKey extends string> = {
[K in keyof T]: IsPathRequired<T[K], TypeKey> extends true ? IfEquals<T[K], any, never, K> : never;
}[keyof T];

Expand All @@ -104,7 +108,7 @@ type RequiredPathKeys<T, TypeKey extends TypeKeyBaseType> = {
* @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
* @returns a record contains required paths with the corresponding type.
*/
type RequiredPaths<T, TypeKey extends TypeKeyBaseType> = {
type RequiredPaths<T, TypeKey extends string> = {
[K in RequiredPathKeys<T, TypeKey>]: T[K];
};

Expand All @@ -114,7 +118,7 @@ type RequiredPaths<T, TypeKey extends TypeKeyBaseType> = {
* @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
* @returns optional paths keys of document definition.
*/
type OptionalPathKeys<T, TypeKey extends TypeKeyBaseType> = {
type OptionalPathKeys<T, TypeKey extends string> = {
[K in keyof T]: IsPathRequired<T[K], TypeKey> extends true ? never : K;
}[keyof T];

Expand All @@ -124,7 +128,7 @@ type OptionalPathKeys<T, TypeKey extends TypeKeyBaseType> = {
* @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
* @returns a record contains optional paths with the corresponding type.
*/
type OptionalPaths<T, TypeKey extends TypeKeyBaseType> = {
type OptionalPaths<T, TypeKey extends string > = {
[K in OptionalPathKeys<T, TypeKey>]?: T[K];
};

Expand All @@ -134,7 +138,7 @@ type OptionalPaths<T, TypeKey extends TypeKeyBaseType> = {
* @param {PathValueType} PathValueType Document definition path type.
* @param {TypeKey} TypeKey A generic refers to document definition.
*/
type ObtainDocumentPathType<PathValueType, TypeKey extends TypeKeyBaseType> = PathValueType extends Schema<any>
type ObtainDocumentPathType<PathValueType, TypeKey extends string > = PathValueType extends Schema<any>
? InferSchemaType<PathValueType>
: ResolvePathType<
PathValueType extends PathWithTypePropertyBaseType<TypeKey> ? PathValueType[TypeKey] : PathValueType,
Expand All @@ -155,7 +159,7 @@ type PathEnumOrString<T extends SchemaTypeOptions<string>['enum']> = T extends (
* @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
* @returns Number, "Number" or "number" will be resolved to number type.
*/
type ResolvePathType<PathValueType, Options extends SchemaTypeOptions<PathValueType> = {}, TypeKey extends TypeKeyBaseType = DefaultTypeKey> =
type ResolvePathType<PathValueType, Options extends SchemaTypeOptions<PathValueType> = {}, TypeKey extends SchemaOptions['typeKey'] = DefaultSchemaOptions['typeKey']> =
PathValueType extends Schema ? InferSchemaType<PathValueType> :
PathValueType extends (infer Item)[] ? IfEquals<Item, never, any[], Item extends Schema ? Types.DocumentArray<ResolvePathType<Item>> : ResolvePathType<Item>[]> :
PathValueType extends StringSchemaDefinition ? PathEnumOrString<Options['enum']> :
Expand Down
22 changes: 11 additions & 11 deletions types/schemaoptions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ declare module 'mongoose' {
currentTime?: () => (NativeDate | number);
}

type TypeKeyBaseType = string;

type DefaultTypeKey = 'type';
interface SchemaOptions<DocType = unknown, TInstanceMethods = {}, QueryHelpers = {}, TStaticMethods = {}, TVirtuals = {}> {
/**
* By default, Mongoose's init() function creates all the indexes defined in your model's schema by
Expand Down Expand Up @@ -139,7 +136,7 @@ declare module 'mongoose' {
* type declaration. However, for applications like geoJSON, the 'type' property is important. If you want to
* control which key mongoose uses to find type declarations, set the 'typeKey' schema option.
*/
typeKey?: TypeKeyBaseType;
typeKey?: string;

/**
* By default, documents are automatically validated before they are saved to the database. This is to
Expand Down Expand Up @@ -186,22 +183,22 @@ declare module 'mongoose' {
* You can suppress the warning by setting { supressReservedKeysWarning: true } schema options. Keep in mind that this
* can break plugins that rely on these reserved names.
*/
supressReservedKeysWarning?: boolean,
supressReservedKeysWarning?: boolean;

/**
* Model Statics methods.
*/
statics?: Record<any, (this: Model<DocType>, ...args: any) => unknown> | TStaticMethods,
statics?: Record<any, (this: Model<DocType>, ...args: any) => unknown> | TStaticMethods;

/**
* Document instance methods.
*/
methods?: Record<any, (this: HydratedDocument<DocType>, ...args: any) => unknown> | TInstanceMethods,
methods?: Record<any, (this: HydratedDocument<DocType>, ...args: any) => unknown> | TInstanceMethods;

/**
* Query helper functions.
*/
query?: Record<any, <T extends QueryWithHelpers<unknown, DocType>>(this: T, ...args: any) => T> | QueryHelpers,
query?: Record<any, <T extends QueryWithHelpers<unknown, DocType>>(this: T, ...args: any) => T> | QueryHelpers;

/**
* Set whether to cast non-array values to arrays.
Expand All @@ -212,11 +209,14 @@ declare module 'mongoose' {
/**
* Virtual paths.
*/
virtuals?: SchemaOptionsVirtualsPropertyType<DocType, TVirtuals, TInstanceMethods>,
virtuals?: SchemaOptionsVirtualsPropertyType<DocType, TVirtuals, TInstanceMethods>;
}

interface DefaultSchemaOptions {
typeKey: 'type'
id: true
typeKey: 'type';
id: true;
_id: '_id';
timestamps: false;
versionKey: '__v'
}
}

0 comments on commit d487695

Please sign in to comment.