0

I have some problems with Typescript and "@botstan/Magic" library in nodejs.
before we get started please read "Magic" documentation.
follow lines:

import Magic from "@botstan/magic";
import * as _ from "lodash";

@Magic
export default class Base {
    [key: string]: any;
    props = {};
    constructor (config = {}) {
        const self = this;
        _.forEach(config, (value, key) => {
            self.__set(key, value);
        });
    }
    __isset (name: string): boolean {
        name = _.snakeCase(name);
        return _.has(this.props, name);
    }
    __unset (name: string): void {
        name = _.snakeCase(name);
        _.unset(this.props, name);
    }
    __set (name: string, value: any): void {
        name = _.snakeCase(name);
        if (value !== null || value !== undefined) {
            _.set(this.props, name, value);
            return;
        }

        _.unset(this.props, name);
    }
    __get (name: string): any {
        name = _.snakeCase(name);
        return _.get(this.props, name, undefined);
    }
}

If you already seen "Magic" documentation, you know we just created a Magic class in Typescript.

import Base from "./Base";

const obj = new Base();
obj.first_name = "Jone";
obj.last_name = "Done";

console.log(obj.first_name); // Jone
console.log(obj); // { props: { first_name: "Jone", last_name: "Done" } }

The "Base" class works well, but our problem started when i got extends from it.

import Base from "./Base";

export default class Example extends Base {
    someVar: any = false;
    someMethod () {
    }
}

For now, let me test Example class.

import Example from "./Example";

const obj = new Example();
obj.first_name = "Jone";
obj.last_name = "Done";

console.log(obj.first_name); // Jone
console.log(obj); // { props: { }, first_name: "Jone", last_name: "Done" }

The "Example" class doesn't works like The "Base" class. What i can do to fix that ?

  • have you tried using the @Magic decorator on the derived class as well ? – Titian Cernicova-Dragomir Sep 08 '18 at 19:40
  • @TitianCernicova-Dragomir Yes, I tried that and it's works but i don't want to repeat it to 100 classes. I want to know, Is there any way to have that ? – MehdiKhody Sep 08 '18 at 20:07
  • That's probably what you should do anyway. It's only an extra six characters per class, minus the import, which is practically none if your editor/IDE has automatic imports. Plus, the presence (or lack) of an annotation will let the person reading the code know that that specific class is supposed to be magic. – kingdaro Sep 09 '18 at 00:54

1 Answers1

0

I read "magic"... and personally it seems like a very worthless library. Personally I wouldn't touch it and pollute my code base with it.

That aside, if you extend a class (Inherit in common OO terminology), and that base class has a constructor, you need to call super() in your derived class (Example in your case), which you're not. It must also be the first call made within the constructor to properly initialize the base class. Try this out and see if it works:

export default class Example extends Base {
    someVar: any = false;

    constructor(){
      super({}); // <-- empty obj because base class takes a single init param    
    }
    someMethod () {
    }
}
dvsoukup
  • 1,586
  • 15
  • 31
  • I don't think the constructor is the problem. If a class doesn't declare a constructor, it gets an implicit one that passes any and all arguments to the super constructor, and the super constructor does have `{}` as a default argument. – Matt McCutchen Sep 09 '18 at 22:23