node.js - Kan inte använda generisk modell i mongoose: Argument av typen 'x' kan inte tilldelas till parametern av typen MongooseFilterQuery
Jag försöker skicka en generell Mongoose-modell som en parameter till en funktion.
import mongoose, { Document, Model, Schema } from 'mongoose';
interface User {
name: string;
age: number;
favouriteAnimal: string;
}
const UserSchema = new Schema({
name: String,
age: Number,
favouriteAnimal: String,
});
const UserModel = mongoose.model<User & Document>('User', UserSchema);
function doSomething() {
return UserModel.findOne({ user: 'john' }); // This is fine.
}
async function doSomethingGeneric<T extends User & Document>(model: Model<T>, key: keyof T) {
const user = await model.findOne({ user: 'john' }); // Compiler errors on this line.
return user![key];
}
Detta är felutdata från kompilatorn:
error TS2345: Argument of type '{ user: string; }' is not assignable to parameter of type 'MongooseFilterQuery<Pick<T, Exclude<keyof T, "toString" | "removeListener" | "off" | "update" | "invalidate" | "increment" | "model" | "$isDeleted" | "remove" | "save" | "__v" | "$isDefault" | "$session" | ... 47 more ... | "modelName">>>'.
Type '{ user: string; }' is not assignable to type '{ [P in keyof Pick<T, Exclude<keyof T, "toString" | "removeListener" | "off" | "update" | "invalidate" | "increment" | "model" | "$isDeleted" | "remove" | "save" | "__v" | "$isDefault" | "$session" | ... 47 more ... | "modelName">>]?: (P extends "_id" ? [...] extends [...] ? Condition<...> : Condition<...> : [...] e...'.
23 const user = await model.findOne({ user: 'john' });
Typen av UserModel är mongoose.Model<User & mongoose.Document, {}>, så jag skulle ha förväntat mig att den generiska uppfyller samma typbegränsningar som den icke-generiska metoden. Var har jag fel?
Redigera: Jag har återskapat problemet i TS-lekplatsen så att du kan se det direkt.
Svar #1
Detta har bekräftats vara en Typescript-bugg: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/39358
En möjlig lösning är att manuellt kasta frågeobjektet till rätt typ:
async function doSomethingGeneric<T extends User & Document>(model: Model<T>, key: keyof T) {
const user = await model.findOne({ user: 'john' } as FilterQuery<T>);
return user![key]; /* add this ^^^^^^^^^^^^^^^^^ */
}
