An example of a base class Entity implementation for Repository pattern

An example of a base class Entity implementation for Repository pattern

Here my objective is to implement a base class named BaseEntiy with some generic method to fetch properties of that class instance in a type safe manner using TypeScript generics.

BaseEntity class has two base methods defined

class BaseEntity<EntityDataType> {
  get<K extends keyof EntityDataType>(
    prop?: keyof EntityDataType
  ): EntityDataType[K] | EntityDataType {
    const data = Object.assign({}, this) as unknown as EntityDataType;
    return prop ? (data[prop] as EntityDataType[K]) : (data as EntityDataType);
  }

  set<K extends keyof EntityDataType>(
    prop: keyof EntityDataType,
    value: EntityDataType[K]
  ): void {
    Object.assign(this, { [prop]: value });
  }
}

So we are set with our Base entity class. Now we need to create a User entity class from the base class. For passing data to the constructor I am here using a UserData type which has all the attribute definition of the Entity User.

The code for the UserData type and User entity can see below

type UserData = {
  name: string;
  email: string;
  ssn: string;
  dob: string;
  age: number;
  address: string;
};

class User extends BaseEntity<UserData> {
  private id: number | null = null;
  private name: string;
  private email: string;
  private ssn: string;
  private dob: string;
  private age: number;
  private address: string;

  constructor({ name, email, ssn, dob, age, address }: UserData) {
    super();
    this.name = name;
    this.email = email;
    this.ssn = ssn;
    this.dob = dob;
    this.age = age;
    this.address = address;
  }
}

So for any new class we extend from the base entity we can use the get and set methods in a type safe manner and we can add any general methods to the base class as well.

The test code is below

describe("Base entity implemenation", () => {
  test("Base entity", () => {
    const userData: UserData = {
      name: "John Doe",
      email: "vimson@gmail.com",
      ssn: "123-456-789",
      dob: "01-01-1990",
      age: 20,
      address: "123 Main St",
    };
    const user = new User(userData);

    expect(user.get("name")).toBe(userData.name);
    expect(typeof user.get("age")).toBe("number");

    expect(user.get()).toEqual(Object.assign({ id: null }, userData));

    user.set("name", "Jane Doe 123");
    expect(user.get("name")).toBe("Jane Doe 123");
  });
});

Yo can refer the code here in GitHub.