I've created a codesandbox for easier trial. But below are also the parts that are more related to my question.
This is the type that is expected to extract the raw Mongoose document's type (It doesn't.):
// ⭐ class Document<T = any, TQueryHelpers = any, DocType = any>
type ObtainRawDocType<T> = T extends mongoose.Document<
infer A,
infer B,
infer C
>
? C // <--- ⭐ Must return the raw document's type.
: never;
This is where the above generic is used (The return type is not right on purpose, in order to test the above generic.):
export function clearFields<
T extends mongoose.Document,
U extends PropertyKey[]
>(dataObj: T, privateFields: U): ObtainRawDocType<T> {
However, this cc1
's type is detected to be unknown
:
const cc1 = clearFields(c1, ["birthdate"]);
this question was also asked on the typegoose discord, where we came to the conclusion that the resulting unknown
is because typescript discards the original type if it has been AND'd with a Omit
type and is not structurally used anywhere.
typescript playground example of the problem
the answer is basically to augment the mongoose.Document
type to structurally use the generic that is wanted (in this case the currently named DocType
generic (mongoose 7.3.1)
// NodeJS: 19.9.0
// MongoDB: 5.0 (Docker)
// Typescript 4.9.5
import { getModelForClass, prop } from '@typegoose/typegoose'; // @typegoose/[email protected]
import * as mongoose from 'mongoose'; // [email protected]
declare module 'mongoose' {
interface Document<T = any, TQueryHelpers = any, DocType = any> {
__DOCTYPE: DocType; // some kind of property to structurally use the generic
}
}
type ObtainRawDocType<T> = T extends mongoose.Document<infer A, infer B, infer C> ? C : never;
function clearFields<T extends mongoose.Document, U extends PropertyKey[]>(dataObj: T, privateFields: U): ObtainRawDocType<T> {
return undefined as any; // Temporary
}
class User {
@prop()
public username?: string;
}
const UserModel = getModelForClass(User);
const c1 = new UserModel({});
const cc1 = clearFields(c1, ['birthdate']);
Notes:
import "mongoose"
has to be done where the declare module "mongoose"
is happening, otherwise the whole mongoose
module / namespace is overwritten instead of augmentedAll declarations of 'Document' must have identical type parameters.ts(2428)