Skip to content

Commit

Permalink
Reolve schema type when timestamps option is true.
Browse files Browse the repository at this point in the history
  • Loading branch information
mohammad0-0ahmad committed Jul 27, 2022
1 parent 41ffde3 commit 8b42562
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 28 deletions.
48 changes: 27 additions & 21 deletions test/types/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
SchemaOptions,
ObtainSchemaGeneric,
DefaultSchemaOptions,
FlatRecord
FlatRecord,
ApplySchemaOptions
} from 'mongoose';
import { expectType, expectError, expectAssignable } from 'tsd';

Expand Down Expand Up @@ -356,7 +357,7 @@ export function autoTypedSchema() {
}
}

type TestSchemaType = {
type TestSchemaType = ApplySchemaOptions<{
string1?: string;
string2?: string;
string3?: string;
Expand Down Expand Up @@ -400,7 +401,7 @@ export function autoTypedSchema() {
decimal1?: Types.Decimal128;
decimal2?: Types.Decimal128;
decimal3?: Types.Decimal128;
};
}>;

const TestSchema = new Schema({
string1: String,
Expand Down Expand Up @@ -533,21 +534,21 @@ export function autoTypedSchema() {
}

export type AutoTypedSchemaType = {
schema: {
schema: ApplySchemaOptions<{
userName: string;
description?: string;
nested?: {
nested?: ApplySchemaOptions<{
age: number;
hobby?: string
},
}>,
favoritDrink?: 'Tea' | 'Coffee',
favoritColorMode: 'dark' | 'light'
friendID?: Types.ObjectId;
nestedArray: Types.DocumentArray<{
nestedArray: Types.DocumentArray<ApplySchemaOptions<{
date: Date;
messages?: number;
}>
}
}>>
}>
, statics: {
staticFn: () => 'Returned from staticFn'
},
Expand All @@ -561,7 +562,7 @@ const eventSchema = new Schema<{ message: string }>({ message: String }, { discr
const batchSchema = new Schema<{ name: string }>({ name: String }, { discriminatorKey: 'kind' });
const discriminatedSchema = batchSchema.discriminator('event', eventSchema);

expectType<Schema<Omit<{ name: string }, 'message'> & { message: string }>>(discriminatedSchema);
expectType<Schema<ApplySchemaOptions<{ name: string } & { message: string }>>>(discriminatedSchema);

function gh11828() {
interface IUser {
Expand Down Expand Up @@ -629,17 +630,17 @@ function gh12030() {
]
});

expectType<{
expectType<ApplySchemaOptions<{
users: {
username?: string
}[];
}>({} as InferSchemaType<typeof Schema1>);
}>>({} as InferSchemaType<typeof Schema1>);

const Schema2 = new Schema({
createdAt: { type: Date, default: Date.now }
});

expectType<{ createdAt: Date }>({} as InferSchemaType<typeof Schema2>);
expectType<ApplySchemaOptions<{ createdAt: Date }>>({} as InferSchemaType<typeof Schema2>);

const Schema3 = new Schema({
users: [
Expand All @@ -650,25 +651,27 @@ function gh12030() {
]
});

expectType<{
users: Types.DocumentArray<{
expectType<ApplySchemaOptions<{
users: Types.DocumentArray<ApplySchemaOptions<{
credit: number;
username?: string;
}>;
}>({} as InferSchemaType<typeof Schema3>);
}>>;
}>>({} as InferSchemaType<typeof Schema3>);


const Schema4 = new Schema({
data: { type: { role: String }, default: {} }
});

expectType<{ data: { role?: string } }>({} as InferSchemaType<typeof Schema4>);
expectType<ApplySchemaOptions<{ data: { role?: string } }>>({} as InferSchemaType<typeof Schema4>);

const Schema5 = new Schema({
data: { type: { role: Object }, default: {} }
});

expectType<{ data: { role?: any } }>({} as InferSchemaType<typeof Schema5>);
expectType<ApplySchemaOptions<{
data: { role?: any }
}>>({} as InferSchemaType<typeof Schema5>);

const Schema6 = new Schema({
track: {
Expand All @@ -683,12 +686,12 @@ function gh12030() {
}
});

expectType<{
expectType<ApplySchemaOptions<{
track?: {
backupCount: number;
count: number;
};
}>({} as InferSchemaType<typeof Schema6>);
}>>({} as InferSchemaType<typeof Schema6>);

}

Expand All @@ -700,4 +703,7 @@ function gh12122() {

const Test2 = new Schema({ test: String }, {});
expectType<DefaultSchemaOptions>({} as ObtainSchemaGeneric<typeof Test2, 'TSchemaOptions'>);

const Test3 = new Schema({ test: String }, { timestamps: true });
expectType<{ test?: string; createdAt: Date; updatedAt: Date; }>({} as InferSchemaType<typeof Test3>);
}
8 changes: 4 additions & 4 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,20 +147,20 @@ declare module 'mongoose' {
export type DiscriminatorModel<M, T> = T extends Model<infer T1, infer T2, infer T3, infer T4>
?
M extends Model<infer M1, infer M2, infer M3, infer M4>
? Model<Omit<M1, keyof T1> & T1, M2 | T2, M3 | T3, M4 | T4>
? Model<FlatRecord<Omit<M1, keyof T1> & T1>, M2 | T2, M3 | T3, M4 | T4>
: M
: M;

export type DiscriminatorSchema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, T> = T extends Schema<infer T1, infer T2, infer T3, infer T4, infer T5>
? Schema<Omit<DocType, keyof T1> & T1, DiscriminatorModel<T2, M>, T3 | TInstanceMethods, T4 | TQueryHelpers, T5 | TVirtuals>
export type DiscriminatorSchema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, T> = T extends Schema<any, any, infer T3, infer T4, infer T5, any, any, infer TDocType>
? Schema<FlatRecord<Omit<DocType, keyof TDocType> & TDocType>, DiscriminatorModel<Model<TDocType>, M>, T3 | TInstanceMethods, T4 | TQueryHelpers, T5 | TVirtuals>
: Schema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals>;

type QueryResultType<T> = T extends Query<infer ResultType, any> ? ResultType : never;

export class Schema<EnforcedDocType = any, M = Model<EnforcedDocType, any, any, any>, TInstanceMethods = {}, TQueryHelpers = {}, TVirtuals = {},
TStaticMethods = {},
TSchemaOptions extends ResolveSchemaOptions<TSchemaOptions> = DefaultSchemaOptions,
DocType extends ObtainDocumentType<DocType, EnforcedDocType, TSchemaOptions> = ObtainDocumentType<any, EnforcedDocType, TSchemaOptions>>
DocType extends ApplySchemaOptions<ObtainDocumentType<DocType, EnforcedDocType, TSchemaOptions>, TSchemaOptions> = ApplySchemaOptions<ObtainDocumentType<any, EnforcedDocType, TSchemaOptions>, TSchemaOptions>>
extends events.EventEmitter {
/**
* Create a new schema
Expand Down
11 changes: 9 additions & 2 deletions types/inferschematype.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
ObjectIdSchemaDefinition,
IfEquals,
SchemaOptions,
DefaultSchemaOptions
DefaultSchemaOptions,
MergeType
} from 'mongoose';

declare module 'mongoose' {
Expand Down Expand Up @@ -64,9 +65,15 @@ declare module 'mongoose' {
* @param {T} T Schema option to be resolved.
*/
type ResolveSchemaOptions<T> = Omit<MergeType<DefaultSchemaOptions, T>, 'statics' | 'methods' | 'query' | 'virtuals'>;

type ApplySchemaOptions<T, O = DefaultSchemaOptions> = FlatRecord<Resolve_timestamps<T, O>>;
}


type Resolve_timestamps<T, O> = O extends { timestamps: false }
? T
: T extends { timestamps: any } ? T : MergeType<T, { createdAt: Date ;updatedAt: Date }>;

/**
* @summary Checks if a document path is required or optional.
* @param {P} P Document path.
Expand Down Expand Up @@ -138,7 +145,7 @@ type OptionalPaths<T, TypeKey extends string > = {
* @param {PathValueType} PathValueType Document definition path type.
* @param {TypeKey} TypeKey A generic refers to document definition.
*/
type ObtainDocumentPathType<PathValueType, TypeKey extends string > = PathValueType extends Schema<any>
type ObtainDocumentPathType<PathValueType, TypeKey extends string > = PathValueType extends Schema
? InferSchemaType<PathValueType>
: ResolvePathType<
PathValueType extends PathWithTypePropertyBaseType<TypeKey> ? PathValueType[TypeKey] : PathValueType,
Expand Down
2 changes: 1 addition & 1 deletion types/utility.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ declare module 'mongoose' {
* @description It makes intellisense dialog box easier to read as a single object instead of showing that in multiple object unions.
* @param {T} T The type to be converted.
*/
type FlatRecord<T> = { [K in keyof T]: T[K] };
type FlatRecord<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;

/**
* @summary Checks if a type is "Record" or "any".
Expand Down

0 comments on commit 8b42562

Please sign in to comment.