0

I am trying to create a model that I can reuse throughout my application which is based heavily off of Eloquents model but not with as many features as this is only the frontend.

I have hit a bit of block though currently.

I am storing all of my data for the Resource inside of an attributes property which is initialised at the top of the class as an empty object. The reason I store it in an attributes property is the class is dynamic so it makes more sense to do it inside of this property.

However this has a bit of a fallback which I don't know if I can avoid... When I instantiate a new class which extends this Resource like the following...

const user: IUser = new User({
    firstName: 'John',
    lastName: 'Doe'
});

I want to be able to then query them attributes directly from the user without having to go through the attributes property so I would like to type user.firstName rather than user.attributes.firstName.

I know in php you can do something like __get() but I don't believe there's magic methods within Typescript so I don't know if this is even achievable.

The basic class looks something like this...

export class Resource {
   attributes!: Attributes;

   constructor(attributes: Attributes = {}) {
       this.attributes = attributes;
   }
}
export class User extends Resource {
    //
}

EDIT: Current solution

After having a bit of a play around with the constructor of the Resource class I have come up with the following...

constructor(attributes: Attributes = {}) {
    Object.keys(attributes).forEach((attributeKey: string) => {
        Object.defineProperty(this, attributeKey, {
            get: () => this.getAttribute(attributeKey),
            set: (value: any) => this.setAttribute(attributeKey, value)
        });
    });
}

This seems to work perfectly, however when targeting a property on that class for example user.firstName it doesn't exist as that is an instance of User and as this class is dynamic it seems like an impossible task to be able to actually assign a type to this, I could make a resource interface which all interfaces extends, would this do the trick?

interface IUser extends IResource {
    firstName: string;
    lastName: string;
}
  • Okay, I have managed to do something a little different so I will update the question... –  Feb 04 '20 at 23:12
  • Looks like it's duplication of https://stackoverflow.com/questions/12827266/get-and-set-in-typescript – Vitalii Ilchenko Feb 04 '20 at 23:14
  • @VitaliiIlchenko I have updated the question, it is not a duplicate –  Feb 04 '20 at 23:20
  • Do you have any logic in `Resource` class or it's just a model? – Vitalii Ilchenko Feb 04 '20 at 23:27
  • @VitaliiIlchenko The `Resource` class does have logic in yes, the example is just in the basic form. The attributes have getters and setters as inside of the Child Resource I am then able to create methods which will alter this attribute, for example `getFirstNameAttribute()` and in here I can add logic that always uppercases the first character and the getter will call this method. –  Feb 05 '20 at 07:56

0 Answers0