英文:
How to register same mongoose hook for multiple methods in TypeScript?
问题
以下是已翻译的内容:
根据 https://stackoverflow.com/questions/67268004/how-to-register-same-mongoose-hook-for-multiple-methods 中的答案:
const hooks = [ 'find', 'findOne', 'update' ];
UserSchema.pre( hooks, function( next ) {
// stuff
}
上述代码在不使用 TypeScript 严格模式时正常工作。一旦启用严格模式,它会报错:No overload matches this call.
我该如何调整代码以解决这个问题?我似乎找不到关于它的详细文档,大多数文档只提供了如何为单个方法而不是一次多个方法做的示例。
英文:
Based on the answer in https://stackoverflow.com/questions/67268004/how-to-register-same-mongoose-hook-for-multiple-methods
const hooks = [ 'find', 'findOne', 'update' ];
UserSchema.pre( hooks, function( next ) {
// stuff
}
The code above works fine when not using TypeScript in strict mode. As soon as I enable strict mode, it complains: No overload matches this call.
How can I adjust the code to fix this? I can't seem to find much documentation about it, most documentation just offers examples of how to do it for a single method instead of multiple at a time.
答案1
得分: 1
你的hooks
变量的推断类型是string[]
。Schema.pre
有各种重载:
/** Defines a pre hook for the model. */
pre<T = THydratedDocumentType>(
method: DocumentOrQueryMiddleware | DocumentOrQueryMiddleware[],
options: SchemaPreOptions & { document: true; query: false; },
fn: PreMiddlewareFunction<T>
): this;
pre<T = Query<any, any>>(
method: DocumentOrQueryMiddleware | DocumentOrQueryMiddleware[],
options: SchemaPreOptions & { document: false; query: true; },
fn: PreMiddlewareFunction<T>
): this;
pre<T = THydratedDocumentType>(method: 'save', fn: PreSaveMiddlewareFunction<T>): this;
pre<T = THydratedDocumentType>(method: 'save', options: SchemaPreOptions, fn: PreSaveMiddlewareFunction<T>): this;
pre<T = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | RegExp, fn: PreMiddlewareFunction<T>): this;
pre<T = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
pre<T = THydratedDocumentType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: PreMiddlewareFunction<T>): this;
pre<T = THydratedDocumentType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: PreMiddlewareFunction<T>): this;
pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
pre<T = M>(method: 'insertMany' | RegExp, fn: (this: T, next: (err?: CallbackError) => void, docs: any | Array<any>) => void | Promise<void>): this;
pre<T = M>(method: 'insertMany' | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err?: CallbackError) => void, docs: any | Array<any>) => void | Promise<void>): this;
正如错误消息告诉你的那样,none of these accepts string[]
as the method
argument,因为有很多有效的字符串值是not valid method names。
然而,如果你更明确地表达你的意图,例如使用query middleware type:
type MongooseQueryMiddleware = 'count' | 'estimatedDocumentCount' | 'countDocuments' | 'deleteMany' | 'deleteOne' | 'distinct' | 'find' | 'findOne' | 'findOneAndDelete' | 'findOneAndRemove' | 'findOneAndReplace' | 'findOneAndUpdate' | 'remove' | 'replaceOne' | 'update' | 'updateOne' | 'updateMany';
你可以满足编译器(并让它检查任何拼写错误,例如它可以告诉你如果 findone
被错误地用于 findOne
):
import { type MongooseQueryMiddleware } from "mongoose";
// ...
const hooks: MongooseQueryMiddleware[] = ["find", "findOne", "update"];
UserSchema.pre(hooks, function (next) {
// stuff
});
或者,你也可以内联数组:
UserSchema.pre(["find", "findOne", "update"], function (next) {
// stuff
});
请注意,如你在上面的评论中所建议的那样使用类型断言 not 是正确的方法。当你这样做时,而不是让编译器检查值是否正确,你坚持要它们正确,所以它不能为你捕获拼写错误:
const hooks = ["find", "findone", "update"] as MongooseQueryMiddleware[];
// ^^^^^^^^^
UserSchema.pre(hooks, function (next) {
// stuff
});
英文:
The inferred type of your hooks
variable is string[]
. Schema.pre
has various overloads:
/** Defines a pre hook for the model. */
pre<T = THydratedDocumentType>(
method: DocumentOrQueryMiddleware | DocumentOrQueryMiddleware[],
options: SchemaPreOptions & { document: true; query: false; },
fn: PreMiddlewareFunction<T>
): this;
pre<T = Query<any, any>>(
method: DocumentOrQueryMiddleware | DocumentOrQueryMiddleware[],
options: SchemaPreOptions & { document: false; query: true; },
fn: PreMiddlewareFunction<T>
): this;
pre<T = THydratedDocumentType>(method: 'save', fn: PreSaveMiddlewareFunction<T>): this;
pre<T = THydratedDocumentType>(method: 'save', options: SchemaPreOptions, fn: PreSaveMiddlewareFunction<T>): this;
pre<T = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | RegExp, fn: PreMiddlewareFunction<T>): this;
pre<T = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
pre<T = THydratedDocumentType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: PreMiddlewareFunction<T>): this;
pre<T = THydratedDocumentType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: PreMiddlewareFunction<T>): this;
pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
pre<T = M>(method: 'insertMany' | RegExp, fn: (this: T, next: (err?: CallbackError) => void, docs: any | Array<any>) => void | Promise<void>): this;
pre<T = M>(method: 'insertMany' | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err?: CallbackError) => void, docs: any | Array<any>) => void | Promise<void>): this;
As the error message tells you, none of these accepts string[]
as the method
argument, because there are plenty of valid string values that are not valid method names.
However if you are more specific about your intentions, e.g. using the query middleware type:
type MongooseQueryMiddleware = 'count' | 'estimatedDocumentCount' | 'countDocuments' | 'deleteMany' | 'deleteOne' | 'distinct' | 'find' | 'findOne' | 'findOneAndDelete' | 'findOneAndRemove' | 'findOneAndReplace' | 'findOneAndUpdate' | 'remove' | 'replaceOne' | 'update' | 'updateOne' | 'updateMany';
you can satisfy the compiler (and get the values checked for any typos, e.g. it could tell you if findone
was accidentally used instead of findOne
):
import { type MongooseQueryMiddleware } from "mongoose";
// ...
const hooks: MongooseQueryMiddleware[] = ["find", "findOne", "update"];
UserSchema.pre(hooks, function (next) {
// stuff
});
Alternatively, you could just inline the array:
UserSchema.pre(["find", "findOne", "update"], function (next) {
// stuff
});
Note that using a type assertion, as suggested in your comment above, is not the right way to go about this. When you do that, rather than letting the compiler check the values you insist to it that they're right, so it can't catch typos for you:
const hooks = ["find", "findone", "update"] as MongooseQueryMiddleware[];
// ^^^^^^^^^
UserSchema.pre(hooks, function (next) {
// stuff
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论