I am new to typescript and I am trying to learn how to use classes.
My goal would be to create a constructor that can take an object as parameter:
{
first_name: 'Bill',
foo: 'Bar'
}
And that the constructor would automatically fill the properties of my instanciated class, but only the declared properties:
export default class User {
// Because of "this[key] = data[key]", I need to tell my class
// that the class User is a key:string => value:any structure
[key: string]:any;
// Here, I define a public property first_name
public first_name:string;
constructor (data:{[index:string] : any}) {
// Here, I get the properties of my Object
let properties = this.getPublicProperties();
// I assign the value only if the key is part of my properties
Object.keys(data).forEach((key:string) => {
if (typeof properties.find((x:string) => x === key) !== 'undefined') {
this[key] = data[key];
}
})
}
getPublicProperties () {
// I'd like that to be based on defined properties above with "public first_name:string"
// The ideal would be that I could define "private" properties that would not be able
// to be filled with that method.
return ['first_name'];
}
}
Let's try with this main code:
import User from './models/User'
let user:User = new User({
first_name: 'Mathieu',
foo: 'bar'
});
console.log(user);
Result:
User { first_name: 'Mathieu' }
Question: So how could I change my getPublicProperties() in order to automatically grab my properties?
The only solution I came to was to initiate my public properties to null:
export default class User {
[key: string]:any;
public first_name:string = null;
private foo:string;
...
getPublicProperties () {
return Object.getOwnPropertyNames(this);
}
}
Now, let's say that solution works, I would like to abstract this behaviour to another class:
export default class Model {
[key: string]:any;
construct (data:{[index:string] : any}) {
let properties = this.getPublicProperties();
Object.keys(data).forEach((key:string) => {
if (typeof properties.find((x:string) => x === key) !== 'undefined') {
this[key] = data[key];
}
})
}
getPublicProperties () {
return Object.getOwnPropertyNames(this);
}
}
import Model from "./Model";
export default class User extends Model{
public first_name:string = null;
private foo:string;
constructor (data:{[index:string] : any}) {
super();
super.construct(data);
}
}
As you can see in my constructor, I have to call super() before calling another method of the constructor, because if I don't, the getPublicProperties abstracted method would not work in my construct() method.
Question: Am I doing it right, or do I miss something in the inheritance functionalities?