Guide on exporting a function from a module as a class property

How to export a function as a class property from a module?

Even if modifiers such as public are added, when a class property points to a function within a module, it behaves as though it is private.

There are multiple ways to define a property (a, b, c in this example) that all achieve the same result, but none allow for defining the function in a separate module to prevent the class body from becoming too large.

// myModule.ts
/** This is a test */
export function func(msg) {
  console.log(msg);
}

// myClass.ts
import * as myModule from './myModule';
export class MyClass {
  a(msg) { return myModule.func(msg); }
  b = (msg) => myModule.func(msg);
  c = myModule.func;
}

// index.ts
import { MyClass } from './MyClass';
const classInstance = new MyClass();
classInstance.a('test'); // works, but cannot access typedefs from module this way
classInstance.b('test'); // achieves the same result as 'c', facing similar issue
classInstance.c('test'); // works, but TypeScript complains about property 'c' not existing on type 'MyClass'

Answer №1

Upon investigation, the issue arises not when working within a TypeScript project, but rather when compiling a TypeScript module containing classes to JavaScript and then using that JavaScript in another context

When compiled by TSC with target=es2020, TypeScript hides properties which are only visible if type definitions are provided. Without type definitions, properties .b and .c trigger errors stating does not exist on type MyClass

In essence, TSC generates executable JavaScript code, but it may not be entirely correct

myClass.js

export class MyClass {
  constructor() {
      Object.defineProperty(this, "b", {
          enumerable: true,
          configurable: true,
          writable: true,
          value: (msg) => myModule.func(msg)
      });
      Object.defineProperty(this, "c", {
          enumerable: true,
          configurable: true,
          writable: true,
          value: myModule.func
      });
  }
  a(msg) {
      return myModule.func(msg);
  }
}

myclass.d.ts

export declare class MyClass {
    a(msg: string): void;
    b: (msg: string) => void;
    c: typeof myModule.func;
}

When compiled by TSC with target=es5, it works without issues as it does not rely on Object.defineProperty

myClass.js

var MyClass = (function () {
  function MyClass() {
      this.b = function (msg) { return myModule.func(msg); };
      this.c = myModule.func;
  }
  MyClass.prototype.a = function (msg) {
      return myModule.func(msg);
  };
  return MyClass;
}());

Interestingly, TSC generates flawless code with target=esnext

myClass.js

import * as myModule from "./myModule";
export class MyClass {
    a(msg) {
        return myModule.func(msg);
    }
    b = (msg) => myModule.func(msg);
    c = myModule.func;
}

In summary, ES5 lacks support for classes, ES2018 uses Object.defineProperty extensively, while ESNext offers cleaner solutions

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

Creating a span element to replace the list item class in a JavaScript Modal Pop-up

I recently set up a portfolio website that showcases my projects. When you click on a project, a modal window opens with a carousel gallery inside. On my .html page, the projects are organized like this: <li class="Project" data-modal="myModal_1"> ...

I would greatly appreciate your assistance in deciphering the JavaScript code provided in the book "Ajax in Action"

While reading through the Ajax in Action book, I came across a code snippet that has left me with a couple of questions. As someone who is new to web programming and still getting to grips with JavaScript, I am hoping for some clarity on the following: ...

What is the best way to guarantee an Array filled with Strings?

Which is the proper way to define a potentially array of strings? Promise<Array<string>> Or Promise<string[]> ...

Is there a way to use moment js to change the date format to just show the month and year?

Want to transform the date time format using momentjs 2017-02-01T00:00:00.000Z into 02-2017 ( month-year ) Looking for a way to change the date format to display only month-year using momentjs? I attempted it like this: var MnthYr = moment(2017-02-01 ...

What is the process for updating the source in an input box?

How can I use JavaScript to update the src value of an iframe based on input? <input class="url" id="url1" type="url" value="youtube url"> <input onclick="changevideo()" class="add-video" id="add-video1" type="submit" value="add to play ...

Warning: Using synchronous XMLHttpRequest on the main thread is no longer recommended as it can negatively impact the user's experience

I encountered an issue with my project while attempting an Ajax request [Warning] Using synchronous XMLHttpRequest on the main thread is now considered deprecated due to its negative impact on user experience. function retrieveReviews() { var reviewsD ...

Changes to the model cannot be realized unless $scope.$apply is used

Are there alternative methods to achieve the desired model change without utilizing $scope injection in an Angular "controller as" approach within the given setup? The HTML: <div data-ng-controller="Buildings as vm"> <select data-ng-model="vm. ...

JavaScript truthy values referring to numbers

According to the rules outlined below: Falsy: false 0 (zero) '' or "" (empty string) null undefinded NaN (e.g. the result of 1/0) Truthy: Anything else I'm puzzled as to why, in the tests that follow, only the number 1 is considered "tr ...

What is the process for integrating Socket io into an external JavaScript file that is connected to an HTML file?

Currently, I am utilizing node js, socket io, and express to develop a multiplayer web game. To begin, the server initiates and listens on port 2000. Upon visiting localhost:2000, the file lobby.html is transmitted using: //app.js const express = require ...

Steps for transforming a JSON into a Class to generate objects

My JSON data is displayed below: var nodeclienthash={ socket:null, init : function() { // Initializing socket.io this.socket = new io.Socket(this.config.host, {port: this.config.port, rememberTransport: false}); } }; I am currently looking t ...

Is there a way to convert the items in the products variable into the more comprehensive detailedProducts?

New to JS, looking for guidance on transforming the products variable into detailedProducts in JavaScript const products = [ { title: 'Yellow Pail', submitterAvatarUrl: 'images/avatars/daniel.jpg', productImageUrl: 'images ...

Identify matching values in objects and dynamically update them with a custom value

I have an array structured like this: var array = [ { dates: "2020-12-25", class: "first" }, { dates: "2020-12-26", class: "last" }, { dates: "2021-06-11", class: "first" }, ...

Searching for an item in an array within MongoDB: Tips and techniques

I am attempting to locate the object containing a specific element within an array: Here is my query: router.get('/', function(req, res) { var userSubscribed = req.user.email; db.posts.find({ "SubscriberList": { $elemMatch: userSubscrib ...

Vue encountered a double loading issue when utilizing a library compiled with Webpack

I am facing an issue with my TypeScript library of Vue components that gets compiled into a single JS file using Webpack. The problem arises when the TypeScript project consuming this library also depends on Vue. Upon running the application, I noticed tha ...

Tips for dodging drawn-out sequences of periods

When working with nested objects using dot notation, it can be tedious to constantly check if each previous object exists. I'm looking for a solution that avoids lengthy if chains like if (a && a.b && a.b.c && a.b.c[0] ... ) ...

Having trouble with a beginner problem that's hindering the functionality of my code

I have been struggling with a particular piece of code and it is driving me crazy as I am unable to locate the source of my error: $.post($form.attr('action'), $form.serialize(), function (result) { console.log(result); if (result.succes ...

What are the steps to code this in Angular14 syntax?

Here's the code snippet: constructor(obj?: any) { this.id = obj && obj.id || null; this.title = obj && obj.title || null; this.description = obj && obj.description || null; this.thumbnailUrl = obj && obj.thumbnailUrl || null; this. ...

JavaScript's Ajax POST request to PHP is not functioning as expected

My current code setup involves handling $_GET[] requests on the products.php page by passing them to get_data_products.php via an ajax POST request. The data retrieved from get_data_products.php is then displayed accordingly. PHP if(isset($_GET['cat ...

The individual is currently tracking his own movements

When developing a function to handle user following and unfollowing, I encountered an issue where the code checking if a user can follow themselves was not functioning as expected. Despite implementing an if statement to prevent self-following, users were ...

Display the option to "Delete" the link only when there are multiple images in my image collection

I am using jQuery and Ajax to remove banner images from my website. However, I want to make sure that if there is only one image left, it cannot be deleted. Each image in the list has a corresponding delete link: echo '<a class="delete j_bannerd ...