Typescript: Best practices for partial entities

1.2k Views Asked by At

I have a pretty basic question but couldn't find anything about it, maybe I'm missing the keywords.

Imagine a basic entity interface and class:

interface EntityInterface {
  id: number;
  name: string;
}

class Entity implements EntityInterface {
  id: number;
  name: string;

  constructor(data: EntityInterface) {
    this.id = data.id;
    this.name = data.name;
  }
}

When I load my data from the server I simply create an Entity with

const entity = new Entity(serverData); //serverData looks like {id: 1, name: 'foo'}

But of course I also want to create a new Entity and send it to the server to persist it. I can't instantiate the empty entity and fill it, because the members have to be defined:

const entity = new Entity(); // => Error: constructor needs parameter
const entity = new Entity({}); // => Error: EntityInterface requires an existing id and name

I know about the Partial utility in Typescript, but I couldn't figure it out how to use it for the current usecase. I thought about setting the EntityInterface parameter in the constructor to Partial. But I definitely want the required-members-typings when having entities loaded from the server.

Then I thought about having a "ServerEntity" class (with required members) and a "PartialEntity" class with optional members. But I do not want to define the members for each class since the members differ only in whether they are required or optional.

I thought about extending the "PartialEntity" from the Entity class, but this would still require the proper data for the constructor:

class PartialEntity extends Entity implements Partial<EntityInterface> {}

const entity = new PartialEntity({}); // => Error: EntityInterface requires an existing id and name

I'm pretty sure there is a solution/best practice to this problem, but I can't figure it out by myself. Any help is highly appreciated!

1

There are 1 best solutions below

6
On

How about using a static method to create an "empty" object that you can then persist? Something like the below

class Entity implements EntityInterface {
  id: number;
  name: string;

  public static EMPTY(): Entity {
     return new Entity({id: node-uuid.v4(), name: defaultValue });
  }

  constructor(data: EntityInterface) {
    this.id = data.id;
    this.name = data.name;
  }
}

And then you can use it like this

someService.persist(Entity.EMPTY());