I have this object:
export class User {
email: string;
hashedPassword: string;
dateCreated: Date;
plan: string;
directAffiliateSignup: boolean;
referralPromoCode: string;
referredBy: Referrer;
constructor({
email,
hashedPassword,
plan,
directAffiliateSignup,
}: UserConstructor) {
this.email = email.toLowerCase();
this.hashedPassword = hashedPassword;
this.dateCreated = new Date();
this.plan = plan;
this.directAffiliateSignup = directAffiliateSignup;
this.referralPromoCode = uuidv4();
this.referredBy = null;
}
signToken(expiry: number | string = 60 * 24): string {
const secret = process.env.JWT_SECRET as Secret;
// { ...this } overcomes error `Expected "payload" to be a plain object`
const token = jwt.sign({ ...this }, secret, {
expiresIn: expiry,
});
return token;
}
async saveToDb(): Promise<InsertOneResult<Document>> {
const collection = getCollection(USERS_COLLECTION_NAME);
const saveResult = await collection.insertOne(this);
if (!saveResult) {
throw new HttpError(500, 'Could not insert user into the database');
}
return saveResult;
}
async addReferrer(referralPromoCode: string): Promise<undefined> {
const validReferrer = await User.findReferrer(referralPromoCode);
if (!validReferrer) return;
this.referredBy = referralPromoCode;
}
static async delete(id: string): Promise<DeleteResult> {
const collection = getCollection(USERS_COLLECTION_NAME);
const user = await User.findById(id);
if (!user) throw new HttpError(404, 'User not found');
const deleteResult = await collection.deleteOne(user);
if (!deleteResult) throw new HttpError(500, 'Could not delete user');
return deleteResult;
}
static async fetchAll(limit: number, skip: number = 0): Promise<any> {
const collection = getCollection(USERS_COLLECTION_NAME);
const users = await collection.find().limit(limit).skip(skip).toArray();
if (!users) throw new HttpError(404, 'Could not find any users');
return users;
}
}
And I want to improve the type of this part (for example):
async saveToDb(): Promise<InsertOneResult<Document>> {
Having Document seems a little vague to me, so I thought the type should instead be this:
Promise<InsertOneResult<User>>
But I don’t know whether the above is right or wrong. The above does not seem to show any linting errors, but I can also do this and it shows no linting errors:
class Dog {
name: string;
}
async saveToDb(): Promise<InsertOneResult<Dog>> {
And I know that the above should definitely be incorrect as the insert does not insert a Dog object.
Does anyone know how to improve this? Just using Document seems against the principle of why we should use typescript in the first place.