Nepoxx Nepoxx - 2 months ago 7
TypeScript Question

Reducing an interface in TypeScript

I have a mongoose model with an interface declaring it as such:

export interface IUserDocument extends mongoose.Document {
surname: string;
lastName: string;
}

export interface IUserModel extends mongoose.Model<IUserDocument> {
myStaticMethodGoesHere(signature: string): void;
}


and the corresponding mongoose schema:

const UserSchema = new mongoose.Schema({
surname: {type: String, required: true},
lastname: {type: String, required: true},
})


Now I have to define how my User is structured 2 times already (mongoose schema AND typescript interface), which isn't DRY and is inconvenient. Unfortunately, if I want to use mongoose's
lean
method, I have to define yet another interface:

export interface ILeanUserDocument {
_id: mongoose.Types.ObjectId;
__v: number;
surname: string;
lastName: string;
}


This is inconvenient and error prone. Is there a way for my lean interface to extend (I don't know the verb to use here) my IUserDocument interface but remove stuff from it?

Answer

Extends is not the only way of adding properties to an interface. I believe you can work with type intersection to achieve what you're looking for. Note that in the example below all the names are just my guesses as to what would be appropriate, feel free to choose whatever you like.

You can define the interface

export interface IUserProperties {
  surname: string;
  lastName: string;
}

export type IUserDocument = mongoose.Document & IUserProperties;

and then later on

interface ILeanUserBase {
  _id: mongoose.Types.ObjectId;
  __v: number;
}

export interface ILeanUserDocument = ILeanUserBase & IUserProperties;

Changes to IUserProperties will be reflected in both IUserModel and IUserDocument

Comments