mwilson
mwilson

Reputation: 12960

TypeScript - 'new up' a class in a better way?

I have a ton of models that I have always been structuring like so:

interface IPerson {
  firstName: string;
  lastName: string;
  fullName: string;
}

class Person implements IPerson {
  public firstName: string;
  public lastName: string;
  public fullName: string;
  constructor(_firstName: string, _lastName: string) {
    this.firstName = _firstName;
    this.lastName = _lastName;
    this.fullName = `${this.firstName} ${this.lastName}`;
  }
}

I then eventually call some api to return some json.

Example Response:

{
    "data": [
    {
      “firstName”: “John”,
      “lastName”: “Doe”
    },
    {
      “firstName”: “Jane”,
      “lastName”: “Doe”
    }
  ]
}

After I get the response, I would then just 'new it up' by doing something simple like:

return response.data.map( d => new Person(d.firstName, d.lastName));

My question:

I have some models that have quite a large set of properties and is seems extremely redundant to pass them in as parameters and bind them to the respective properties (at least that's what it feels like). Is there a more elegant way of doing this?

I see a lot of things that are similar to the below examples, but none of them seems to actually 'new up' the object in the class so it behaves correctly (ie: concatenating firstName and lastName).

Similar articles seems to mention something like this:

var modal: IModal = {
    content: '',
    form: '',
    href: '',
    $form: null,
    $message: null,
    $modal: null,
    $submits: null
};

other mention something along the lines of this:

modal: IModal = <IModal>{}

or

var modal = {} as IModal 

Upvotes: 1

Views: 653

Answers (2)

Hikmat G.
Hikmat G.

Reputation: 2621

You can use Object.assign in order not to list properties every time, but instead use data object itself. - example

UPDATE: declared a filter function to remove properties that not are not part of the class from source data. But there is drawback, that class properties have to have initial values in order them to appear in compiled javascript code. If they don't have initial values typescript class will be compiled empty, and there will no way of getting list of properties of typescript class in runtime.

function filter(obj, data) {
  return Object.getOwnPropertyNames(obj).reduce((acc, k) => {
    acc[k] = data[k];
    return acc;
  }, {})
}

class Person implements IPerson {
  public firstName: string = "";
  public lastName: string = "";
  public get fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
  constructor(data) {
    Object.assign(this, filter(this, data))
  }

}

Upvotes: 2

Robert Stiffler
Robert Stiffler

Reputation: 725

Write a constructor that takes an IPerson

interface IPerson {
  firstName: string;
  lastName: string;
  fullName: string;
}

class Person implements IPerson {
  public firstName: string;
  public lastName: string;
  public fullName: string;
  constructor(_firstName: string, _lastName: string) {
    this.firstName = _firstName;
    this.lastName = _lastName;
    this.fullName = `${this.firstName} ${this.lastName}`;
  }
  public static fromIPerson(person: IPerson): Person {
    return new Person(person.firstName, person.lastName);
  }
}

Upvotes: 3

Related Questions