Disclaimer: this post might come across as impulsive. Warning for Typescript beginners! Also, a bit of a vent session.
Recently, I delved into the OLOO approach from the YDKJS book series within a Typescript and Node environment.
// ideal JS syntax
let Account = {
get id(){
return this._id;
},
get name(){
return this._name;
},
init(id, name){
this._id = id;
this._name = name;
}
}
let TypedAccount = {
identify(){
console.log(`This is ${this.name}'s ${this._type} account`);
},
init_L2(type){
this._type = type;
}
}
Object.setPrototypeOf(TypedAccount, Account);
function createAccount(id, name, type){
let instance = Object.create(TypedAccount);
instance.init(id, name);
instance.init_L2(type);
return instance;
}
let o1 = createAccount(101, 'Tom', 'Savings'),
o2 = createAccount(102, 'Jerry', 'Current');
console.log (o1.identify());
console.log (o2.identify());
The primary appeal of OLOO was its simplicity. However, due to the Typescript compiler, I find myself writing more code than necessary; something I wouldn't have to do with the class-based approach.
- I have to define an interface like IAccount for each type like Account, in order to ensure client usages can be checked for/auto-completed. Although, I sometimes resort to using the any escape when needed.
- TS complains about using undeclared fields, so I need to specify all the fields and their types before accessing them with this.field. It's not too much effort but still adds complexity. For example, _id : defaultValue;
- When dealing with object literals that include a map [strings => numbers], I use a nested object. But TS requires me to provide the type for both key and value. This leads to creating an interface to annotate the field.
interface IMapStringsToNumbers {
[ key: string ]: number;
}
//
let Account = {
_holdings : <IMapStringsToNumbers> {}
Perhaps the last two points are not directly related to OLOO. Is there a simpler solution?