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;
}