简体   繁体   中英

How to inject custom function to class in typescript

I would like to inject a custom function into my class from variable functions , how can I do this?

My code is:

const functions = {
    foo: () => console.log('foo') 
}

class ParentBase {
    parentHello() {
        console.log('parentHello')
    }
}

function Base() {
    class BaseClass extends ParentBase { }
    BaseClass.foo = functions['foo']
    return BaseClass;
} 

const Class = Base();
const instance = new Class(); 

instance.parentHello() // it work
instance.foo() // foo  is not a function 

You could directly declare a new method in the class declaration:

class BaseClass extends ParentBase { 
  foo() {functions["foo"](); }
}

If the method name should be dynamic, you can also use computed method names:

class BaseClass extends ParentBase { 
  [window.location]() {functions["foo"](); }
}

If you really want to "dynamically inject" a new method (eg conditionally, in a loop, or some other strange construct), you'd have to write into BaseClass.prototype , which is the object BaseClass instances will inherit from:

BaseClass.prototype.foo = functions["foo"];

This will however be an enumerable property, to create a non enumerable one, use Object.defineProperty :

Object.defineProperty(BaseClass.prototype, "foo", {
  value: functions["foo"],
  /* enumerable: false,
     writable: false */
});

Here is a small showcase:

 class ParentBase { parentHello() { console.log('parentHello') } } function Base() { class BaseClass extends ParentBase { instanceMethod() { console.log("BaseClass.prototoype.test", this); }; static classMethod() { console.log("BaseClass.classMethod", this); }; } BaseClass.classMethod2 = function() { console.log("BaseClass.classMethod2", this); }; BaseClass.prototype.instanceMethod2 = function() { console.log("BaseClass.prototype.instanceMethod2", this); }; Object.defineProperty(BaseClass.prototype, "instanceMethod3", { value() { console.log("BaseClass.prototype.instanceMethod3", this); } }); return BaseClass; } const Class = Base(); const instance = new Class(); Class.classMethod(); Class.classMethod2(); instance.instanceMethod(); instance.instanceMethod2(); instance.instanceMethod3();

You have 2 places to access properties:

  • Instance based
  • Class Based

What you have is adding to class but you are trying to access using instance.

What you are trying to achieve is called Mixins. These are partial utility functions list that can be shared across multiple classes.

To inject properties to instances, you can either use constructor based approach or you can inject them to prototype

 class ParentBase { parentHello() { console.log('parentHello') } } const mixin = { foo: function() { console.log('foo') }, bar: function() { console.log('Bar') }, fooBar: function() { console.log('foo-bar') } } function Base() { class BaseClass extends ParentBase {} Object.assign(BaseClass.prototype, mixin) return BaseClass; } const Class = Base(); const instance = new Class(); instance.parentHello() // it work instance.foo() // foo is not a function instance.fooBar()


You should also know that functions/ properties added on prototype are shared across instances. So its advice to have function but not variables as it will introduce side-effect

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM