Skip to content

Commit

Permalink
Merge pull request #12196 from hasezoey/pluginOptions
Browse files Browse the repository at this point in the history
fix(types): add schema plugin option inference
  • Loading branch information
vkarpov15 committed Aug 3, 2022
2 parents 53dc72b + 4e95e33 commit 67c2e93
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
35 changes: 35 additions & 0 deletions test/types/schema.test.ts
Expand Up @@ -702,3 +702,38 @@ function gh12030() {
}>({} as InferSchemaType<typeof Schema6>);

}

function pluginOptions() {
interface SomePluginOptions {
option1?: string;
option2: number;
}

function pluginFunction(schema: Schema<any>, options: SomePluginOptions) {
return; // empty function, to satisfy lint option
}

const schema = new Schema({});
expectType<Schema<any>>(schema.plugin(pluginFunction)); // test that chaining would be possible

// could not add strict tests that the parameters are inferred correctly, because i dont know how this would be done in tsd

// test basic inferrence
expectError(schema.plugin(pluginFunction, {})); // should error because "option2" is not optional
schema.plugin(pluginFunction, { option2: 0 });
schema.plugin(pluginFunction, { option1: 'string', option2: 1 });
expectError(schema.plugin(pluginFunction, { option1: 'string' })); // should error because "option2" is not optional
expectError(schema.plugin(pluginFunction, { option2: 'string' })); // should error because "option2" type is "number"
expectError(schema.plugin(pluginFunction, { option1: 0 })); // should error because "option1" type is "string"

// test plugins without options defined
function pluginFunction2(schema: Schema<any>) {
return; // empty function, to satisfy lint option
}
schema.plugin(pluginFunction2);
expectError(schema.plugin(pluginFunction2, {})); // should error because no options argument is defined

// test overwriting options
schema.plugin<any, SomePluginOptions>(pluginFunction2, { option2: 0 });
expectError(schema.plugin<any, SomePluginOptions>(pluginFunction2, {})); // should error because "option2" is not optional
}
4 changes: 3 additions & 1 deletion types/index.d.ts
Expand Up @@ -157,6 +157,8 @@ declare module 'mongoose' {

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

type PluginFunction<DocType> = (schema: Schema<DocType>, opts?: any) => void;

export class Schema<EnforcedDocType = any, M = Model<EnforcedDocType, any, any, any>, TInstanceMethods = {}, TQueryHelpers = {}, TVirtuals = {},
TStaticMethods = {},
TPathTypeKey extends TypeKeyBaseType = DefaultTypeKey,
Expand Down Expand Up @@ -239,7 +241,7 @@ declare module 'mongoose' {
pathType(path: string): string;

/** Registers a plugin for this schema. */
plugin(fn: (schema: Schema<DocType>, opts?: any) => void, opts?: any): this;
plugin<PFunc extends PluginFunction<DocType>, POptions extends Parameters<PFunc>[1] = Parameters<PFunc>[1]>(fn: PFunc, opts?: POptions): this;

/** Defines a post hook for the model. */
post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: PostMiddlewareFunction<T, T>): this;
Expand Down

0 comments on commit 67c2e93

Please sign in to comment.