Distribute the capabilities of the class

Is there a way to transfer the functionalities of a class into another object? Let's consider this example:

class FooBar {
    private service: MyService;

    constructor(svc: MyService) {
       this.service = svc;
    }

    public foo(): string {
        return "foo";
    }

    public bar(): string {
        return "bar"
    }

    public fooBar(): string {
        return "foobar"
    }
}

let obj = new FooBar();

export default {
    ...obj
};

I am looking to have all the methods of the class FooBar in the exported object without including the private property service. However, since these methods are added to the prototype object in JavaScript compilation, they are not part of the spread operation and the private property ends up included in the resulting object.

One solution that works is:

export default {
    foo: obj.foo.bind(obj),
    bar: obj.bar.bind(obj),
    fooBar: obj.fooBar.bind(obj),
};

If possible, I would like to avoid this approach as I will need to map methods from multiple classes.

Important Note: This is specifically for combining GraphQL resolvers into a single object to be used with the graphql function.

I am currently running my application using ts-node, in case that matters.

Answer №1

I encountered a few issues in my coding process. Initially, I mistakenly set es6 as the output instead of es5, which resulted in the compiled object lacking a prototype.

Additionally, simply using the spread operator led to the private property service being included in the exported object. To address this problem, I decided to create a helper function with guidance from @Vivick and @AlekseyL:

function combineResolvers(...resolvers: any[]): any {
    let out: { [key: string]: any } = {}
    resolvers.forEach(resolver => {
        let proto = Object.getPrototypeOf(resolver)
        Object.keys(proto)
            .filter(key => {
                return isFunction(resolver[key]);
            }).forEach(key => {
                out[key] = resolver[key].bind(resolver)
            })
    })

    return out
}

function isFunction(functionToCheck: any): boolean {
    return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
}

However, this solution still presented an issue of including private functions from the resolver classes in the exported object.

Answer №2

Using arrow functions and Object.assign for method binding might be a good solution in this case.

class BarFoo {
  private api: YourService;

  constructor(svc: YourService) {
    this.api = svc;
  }

  public bar = (): string => {
    return "bar";
  }

  public foo = (): string => {
    return "foo";
  }

  public barFoo = (): string => {
    return "barfoo";
  }
}

export default { ...Object.assign(new BarFoo()) };

Before implementing this, it's worth checking out this article for insights:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Bidirectional communication linking an Angular 2 component and service utilizing the power of Observables

I'm having difficulties establishing a simple connection between an Angular 2 component and service using Observable. I've been trying to achieve this, but I can't seem to get it right. Here's the scenario: My component HeroViewerCompo ...

Personalized Element Commands and features

UniquePage.html <div ng-controller="UniquePageCtrl"> <unique-custom-directive arg1="{{currentObj.name}}"></my-custom-directive> <div> in UniquePageCtrl.js (Controller) app.controller("UniquePageCtrl", ["$scope", function ($sc ...

Is there a way to upload a file and FormData simultaneously without storing the file on the server's disk?

When it comes to uploading files and FormData to a server, I found a method that works well: On the client side, I am using Angular 2 with the following logic: 1. In the component onLoadForeignLightCompanies(event: any) { let fileList: FileList = ev ...

Showcasing text behind an element with reduced opacity when the element directly above it is selected using rails, CSS, and jQuery

I have a password field on my page where the password is hidden, but I want users to be able to copy and paste the clear text version of the password on another website. In order to achieve this, I followed the instructions in an article titled Mask text, ...

Tips on efficiently reusing shared components within recursive union types in TypeScript

Summary Here's a simple working example in the TypeScript playground: type SimpleExpression = number | string | AddOperator<SimpleExpression> | PrintOperator<SimpleExpression>; type ExtendedExpression = number | string | AddOperator<E ...

Reverting to the original order in jQuery DataTables after dropping a row

Recently, I've been attempting to utilize jQuery DataTables in conjunction with the Row Ordering plugin. At first, everything seemed to be functioning properly until a javascript error popped up indicating an unrecognized expression. After researching ...

Is it possible for me to take action on and then pass along the outcomes of an AngularJS $http request without relying on $q?

I have a function called getData that retrieves data from an API endpoint. My current implementation utilizes $q to handle promises. After processing the retrieved data, I return another promise: var getData = function (controller) { var defer = $q.d ...

Before I press enter, what kind of function is evaluated by the Node.JS REPL?

It's interesting how in the Node.JS REPL, the result of the current expression sometimes gets evaluated before hitting enter, which raises questions. I find it puzzling: How does Node.JS determine if I intended to evaluate it or not? Simple calculati ...

Storing Array Data in Angular $scope (Javascript)

I am currently altering the Altair Material Design Template and incorporating an Angular JS controller. After successfully calling an API and creating variables in a for loop, I intend to write them to $scope.dragulaItems. While this process seems to work ...

Considering a Servlet for managing AJAX requests?

Looking for advice on best practices for implementing a yes or no question with AJAX requests. Open to feedback if I make any missteps along the way. I have a specific Servlet (AjaxServlet?) designated to handle all AJAX requests AjaxServlet is mapped t ...

Error encountered when attempting to insert data into a PostgreSQL database using Node.js and Sequelize

I'm currently using the node sequelize library to handle data insertion in a postgress database. Below is the user model defined in the Users.ts file: export class User extends Sequelize.Model { public id!: number; public name: string; public ...

Sending a string value from an object to a component by clicking a button in Angular

Within the HTML template of my component 'a', there is a button designed to redirect to another component: <button nbButton status="info" class="left" [routerLink]="['/centers', center.id, 'prices']">PRICES</button&g ...

Tips for managing the second datepicker for the return journey on Abhibus using Selenium webdriver

I am currently working on a code to choose departure date and return journey date, but I am encountering an issue where the return journey date is not being selected. The driver seems to be skipping over the return date selection and proceeding directly to ...

Is it possible for the r.js optimizer to generate a fresh index.html file that links to the compiled files

After using r.js to optimize my project, I'm wondering how to generate a single index.html file that includes just one optimized script and one CSS file. Would I need to manually write this post-build or is there another way to achieve this? ...

When attempting to parse a JSON feed with jQuery and innerHTML, the data fails to display

Having trouble parsing a JSON feed using jQuery and innerHTML, but for some reason it's not working as expected. No errors are being displayed in the console and the feed itself is functioning properly. Not quite sure why this issue is occurring. < ...

What is the best way to store the outcome of a promise in a variable within a TypeScript constructor?

Is it possible to store the result of a promise in a variable within the constructor using Typescript? I'm working with AdonisJS to retrieve data from the database, but the process involves using promises. How do I assign the result to a variable? T ...

The countdown feature is failing to update despite using the SetInterval function

My goal is to develop a countdown application using Atlassian Forge that takes a date input and initiates the countdown based on the current date. For instance, if I input "After 3 days from now," I am expecting the result to continuously update every seco ...

Loop through the JSON data to obtain distinct values for certain indices

My PHP script retrieves data with the following query: SELECT objective,signal_type,signal_name FROM signals WHERE channel="Email" This is how the data is returned: [ { "objective": "Awareness", "signal_type": "Efficiency", " ...

Is it possible to delete a <div> tag based on screen size using jQuery or JavaScript?

Hello, I was curious if it's possible to dynamically remove a specific div tag using jQuery or JavaScript when the screen reaches a certain size, for example 500px. ...

Is there a way to utilize Angular in identifying whether a given value corresponds with the value of a particular radio button within my application?

I have an array of lists that I need to display in radio buttons. Like this: https://i.stack.imgur.com/cmYgO.png https://i.stack.imgur.com/Zx4bm.png https://i.stack.imgur.com/jBTe3.png My goal is to have a checkbox that matches the values loaded from a ...