Created
March 31, 2021 14:33
-
-
Save ospatil/30dfd93d6632505e431fd894f552772f to your computer and use it in GitHub Desktop.
TypeScript type LeanDocument for mongoose and nestjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Doc { | |
attrA: string; | |
attrB: string; | |
id: string; | |
_id: any; | |
_v: number; | |
func1 = () => {} | |
func2 = () => {} | |
} | |
class MyDocument extends Doc { | |
attrC: string; | |
attrD: string; | |
_id: string; | |
} | |
type LeanDocument<C, P extends {_id: unknown}> = Pick<C, Exclude<keyof C, keyof P>> & Pick<P, Extract<keyof P, "id" | "_v">> & { | |
_id: C extends { _id: unknown } ? C['_id'] : P['_id']; | |
}; | |
const myDoc:MyDocument = new MyDocument(); | |
// try typing myDoc. and see that all properties from MyDocument and Doc are available | |
// myDoc. | |
const leanDoc:LeanDocument<MyDocument, Doc> = myDoc; | |
// Now try typing excluded. The only proerties available are attrC, attrD, id, _id and _v | |
// leanDoc. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Model, Document } from 'mongoose'; | |
export type LeanDocument<C extends Document, P extends Document> = Pick< | |
C, // pick keys from C i.e. User provided document object | |
Exclude<keyof C, keyof P> // Remove all attributes and methods coming from Document | |
> & | |
Pick<P, Extract<keyof P, 'id' | '_v'>> & { | |
// Above: extract and pick id (which is a virtual prop) & _v from Document | |
_id: C extends { _id: unknown } ? C['_id'] : P['_id']; // Use user-provided custom _id if available | |
}; | |
//... | |
//... | |
export abstract class BaseService<T extends Document> { | |
constructor(protected readonly _model: Model<T>) {} | |
protected toObject(doc: T): object { | |
return doc.toObject({ virtuals: true, getters: true }); | |
} | |
async findAll(query): Promise<LeanDocument<T, Document>[]> { | |
return this.findDocuments(query).then((docs) => | |
docs.map(this.toObject.bind(this)) | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment