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

When attempting to retrieve information using the findById(''), the process became frozen

When attempting to retrieve data using findById(), I'm encountering a problem. If I provide a correct ObjectID, the data is returned successfully. However, if I use an invalid ObjectID or an empty string, it gets stuck. If findById() is called with a ...

Using SCSS variables in TypeScript inside a Vue project

Has anyone had experience with importing SASS (scss) variables into JavaScript in a TypeScript Vue 3 project? // @/assets/styles/colors.scss $white: #fff; // @/assets/styles/_exports.scss @import "./colors.scss"; :export { white: $white; } <templat ...

JavaScript encountered an unexpected symbol, specifically the "=>" token

I encountered an issue while attempting to create a JavaScript function for deployment on Firebase: Error Message: Parsing error: Unexpected token => Here is the code snippet: exports.sendFriendRequest = functions.firestore.document("requests/{rUi ...

Preload-webpack-plugin does not support pre-fetching files

I have a query about prefetching and preloading content. In my vue app, I noticed that after building, I have duplicate files loaded in my dist/index.html file. Here is an example: Additionally, the "scripts" are not being preloaded/prefetched as expec ...

How to automatically close the menu on a Wordpress theme after clicking a link

I am currently using a Wordpress theme named ichiban, which can be viewed by following this link. Within this theme, I have created custom menu items that are designed to link directly to different sections on the same page. However, I am encountering an i ...

Dealing with the Spread operator in React and Redux causes issues

As a newcomer to the world of React and Redux, I find myself facing compilation errors while working on a reducer due to my attempt to utilize the spread operator. export default function chaptersReducer( state = { chapters: {}, isFetching: false, error ...

Loading information in a directive by utilizing promises in a service with AngularJS

Can anyone lend a hand? I've been struggling to solve this issue. I created a directive (see below) to display a pre-written ul-list on a page using html data fetched asynchronously from a database server. Both the Directive and The Service are funct ...

Import necessary styles into the shadow DOM

Embracing the concept of shadow dom styles encapsulation is exciting, but I wish to incorporate base styles into each shadow dom as well (reset, typography, etc). <head> <link rel="stylesheet" href="core.css"> ... </h ...

Ajax fails to transmit data to PHP script

Having encountered an issue with my script that prevents sending data from AJAX to a PHP file, I decided to debug it by logging the form data before running it through the AJAX function. The data obtained was as follows: Form: name=jim&email=info%40te ...

The Bootstrap 3.3 Carousel is stationary and does not rotate

I am facing a challenge with implementing a Carousel using Bootstrap version 3.3.7 on my website. The code snippet is as follows: <!-- Carousel ================================================== --> <div class="row dark-start d-none d-lg-block"&g ...

The save feature becomes dysfunctional after switching to the Material-UI dependency in a React project

After integrating the Material-UI dependency into my ReactJS code, I encountered an issue where the "save" functionality no longer works properly. Previously, when editing a task in my simple Todo list app, the new name would be saved successfully. However ...

The deployment of the Fire-base Cloud Function was successful and error-free. However, the function does not appear to exist in the Firebase system

After deploying a JavaScript Cloud Function, it shows that the deployment is completed. However, when I check Firebase, the function is not there. Oddly, TypeScript Cloud Functions deploy successfully. I followed all the steps outlined in the original Fir ...

Utilizing Vue.js to set the instance global property as the default value for a component prop

Is it possible to access a global property from my vue instance when setting a default prop value in my component? This is what I would like to achieve props: { id: { type: String, default: this.$utils.uuid } } I attempted to use an arrow fun ...

Issues with applying styles to custom components in styled-components

I attempted to customize the inner elements of react-id-swiper using the code below: import Swiper from 'react-id-swiper'; import styled from 'styled-components'; const MySwiper = ({ className, children }) => ( <Swip ...

Chaining promises: The benefits of attaching an error handler during Promise creation versus appending it to a variable containing a promise

function generatePromise() { return new Promise((resolve, reject) => { setTimeout(reject, 2000, new Error('fail')); }); } const promise1 = generatePromise(); promise1.catch(() => { // Do nothing }); promise1 .then( ...

Is there a way to incorporate my getter into a computed property?

My Vuex Store is built using Vuex module decorators and I am facing an issue with using a getter for a computed property. Here is my code: @Module export default class WorkoutModule extends VuexModule { _workout: Workout; @Mutation startWork ...

Identify and troubleshoot scripts that are included in the response returned by Chrome

I am facing an issue where I have a webpage that loads HTML sections through an AJAX call. The response includes both HTML and JavaScript files. Currently, I am trying to figure out how to set a debug point on the JavaScript file. In Internet Explorer, I ...

Issue with jQuery .hover() not functioning as expected

The issue I'm encountering is just as described in the title. The code functions correctly on all divs except for one! $(".complete-wrapper-1").hide(); var panelHH = $(".file-select-wrapper").innerHeight; $(".files-button").hover(function(){ $(" ...

The expected result is not obtained when making an Ajax request to a PHP variable

I recently encountered an issue with my AJAX GET request. The response I received was unexpected as the PHP variable appeared to be empty. Here is the snippet of jQuery code that I used: jQuery(document).ready(function($) { $.ajax({ url: '/wp ...

What is the best way to implement an Angular application within the child routes of another Angular application?

Is it possible to load an Angular app using lazy-loading (when a specific route is hit by users) into another Angular app without compiling the first one for use in the second? This is the Routing-Module of the app to nest into an Angular app: const upgr ...