Skip to content

Commit

Permalink
Add ability to infer path of mixed array type.
Browse files Browse the repository at this point in the history
  • Loading branch information
mohammad0-0ahmad committed Apr 5, 2022
1 parent e5509e3 commit e82e7d1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 16 deletions.
11 changes: 10 additions & 1 deletion test/types/schema.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Schema, Document, SchemaDefinition, Model, Types, InferSchemaType, SchemaType, Query, HydratedDocument } from 'mongoose';
import { expectType, expectError, expectAssignable } from 'tsd';
import { IsTAny } from '../../types/inferschematype';

enum Genre {
Action,
Expand Down Expand Up @@ -359,6 +360,10 @@ export function autoTypedSchema() {
customSchema?: Int8;
map1?: Map<string, string>;
map2?: Map<string, number>;
array1?: string[];
array2?: Schema.Types.Mixed[];
array3?: Schema.Types.Mixed[];
array4?: Schema.Types.Mixed[];
};

const TestSchema = new Schema({
Expand Down Expand Up @@ -390,7 +395,11 @@ export function autoTypedSchema() {
objectId3: 'objectId',
customSchema: Int8,
map1: { type: Map, of: String },
map2: { type: Map, of: Number }
map2: { type: Map, of: Number },
array1: { type: [String] },
array2: { type: Array },
array3: { type: [Schema.Types.Mixed] },
array4: { type: [{}] }
});

type InferredTestSchemaType = InferSchemaType<typeof TestSchema>;
Expand Down
34 changes: 19 additions & 15 deletions types/inferschematype.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ declare module 'mongoose' {
* // result
* type UserType = {userName?: string}
*/
type InferSchemaType<SchemaType> = SchemaType extends Schema<infer DocType>
? IsItRecordAndNotAny<DocType> extends true ? DocType : ObtainSchemaGeneric<SchemaType, 'DocType'>
type InferSchemaType<SchemaType> = SchemaType extends Schema<infer EnforcedDocType>
? IsItRecordAndNotAny<EnforcedDocType> extends true ? EnforcedDocType : ObtainSchemaGeneric<SchemaType, 'DocType'>
: unknown;

/**
Expand All @@ -51,7 +51,9 @@ declare module 'mongoose' {
* @param {T} T A generic type to be checked.
* @returns true if {@link T} is Record OR false if {@link T} is of any type.
*/
type IsItRecordAndNotAny<T> = T extends any[] ? false : T extends Record<any, any> ? true : false;
type IsItRecordAndNotAny<T> = IsTAny<T> extends true ? false : T extends Record<any, any> ? true : false;

type IsTAny<T> = keyof any extends keyof T ? (unknown extends T ? true : false) : false;

/**
* @summary Required path base type.
Expand Down Expand Up @@ -128,15 +130,17 @@ type PathEnumOrString<T extends SchemaTypeOptions<string>['enum']> = T extends (
* @returns Number, "Number" or "number" will be resolved to string type.
*/
type ResolvePathType<PathValueType, Options extends SchemaTypeOptions<PathValueType> = {}> =
PathValueType extends (infer Item)[] ? ResolvePathType<Item>[] :
PathValueType extends StringConstructor | 'string' | 'String' | typeof Schema.Types.String ? PathEnumOrString<Options['enum']> :
PathValueType extends NumberConstructor | 'number' | 'Number' | typeof Schema.Types.Number ? number :
PathValueType extends DateConstructor | 'date' | 'Date' | typeof Schema.Types.Date ? Date :
PathValueType extends BufferConstructor | 'buffer' | 'Buffer' | typeof Schema.Types.Buffer ? Buffer :
PathValueType extends BooleanConstructor | 'boolean' | 'Boolean' | typeof Schema.Types.Boolean ? boolean :
PathValueType extends 'objectId' | 'ObjectId' | typeof Schema.Types.ObjectId ? Schema.Types.ObjectId :
PathValueType extends ObjectConstructor | typeof Schema.Types.Mixed ? Schema.Types.Mixed :
keyof PathValueType extends never ? Schema.Types.Mixed :
PathValueType extends MapConstructor ? Map<string, ResolvePathType<Options['of']>> :
PathValueType extends typeof SchemaType ? PathValueType['prototype'] :
unknown;
IsTAny<PathValueType> extends true ? Schema.Types.Mixed:
PathValueType extends (infer Item)[] ? ResolvePathType<Item>[] :
PathValueType extends StringConstructor | 'string' | 'String' | typeof Schema.Types.String ? PathEnumOrString<Options['enum']> :
PathValueType extends NumberConstructor | 'number' | 'Number' | typeof Schema.Types.Number ? number :
PathValueType extends DateConstructor | 'date' | 'Date' | typeof Schema.Types.Date ? Date :
PathValueType extends BufferConstructor | 'buffer' | 'Buffer' | typeof Schema.Types.Buffer ? Buffer :
PathValueType extends BooleanConstructor | 'boolean' | 'Boolean' | typeof Schema.Types.Boolean ? boolean :
PathValueType extends 'objectId' | 'ObjectId' | typeof Schema.Types.ObjectId ? Schema.Types.ObjectId :
PathValueType extends ObjectConstructor | typeof Schema.Types.Mixed ? Schema.Types.Mixed :
PathValueType extends MapConstructor ? Map<string, ResolvePathType<Options['of']>> :
PathValueType extends ArrayConstructor ? Schema.Types.Mixed[] :
keyof PathValueType extends keyof {} ? Schema.Types.Mixed :
PathValueType extends typeof SchemaType ? PathValueType['prototype'] :
unknown;

0 comments on commit e82e7d1

Please sign in to comment.