What is the process for specifying a method on a third-party class in TypeScript?

I'm facing a challenge while trying to extend a third-party class in TypeScript. The issue is that I am unable to access any existing methods of the class within my new method.

One possible solution could be to redeclare the existing methods in a separate file called extensions.ts (as shown below), but I believe there must be a more efficient approach.

Third-Party index.d.ts

export as namespace thirdParty;

export Class SomeClass {
  // various methods here
}

My Custom extensions.ts

import {thirdParty} from 'thirdParty'

declare module 'thirdParty' {
    namespace thirdParty {
        class SomeClass{
            newCustomMethod(): this

            // only functional if I redefine the method here
            originalExistingMethod(): number
        }
    }
}

thirdParty.SomeClass.prototype.newCustomMethod = function() {
    return this.originalExistingMethod() + 1
}

But, when attempting to use an existing method such as this.originalExistingMethod() within the custom function above, TypeScript throws an error:

TS2339: Property 'originalExistingMethod' does not exist on type 'SomeClass'

Is there a way to avoid having to redeclare existing methods during module augmentation?

Answer №1

New Answer

Here is an illustration demonstrating the augmentation of classes using the Tensorflow library.

extend.ts

import { AdadeltaOptimizer } from '@tensorflow/tfjs-core';

declare module '@tensorflow/tfjs-core' {
    interface AdadeltaOptimizer {
        newMethod(message: string): void;
    }
}

AdadeltaOptimizer.prototype.newMethod = function (message: string) {
    console.log('===============');
    console.log(message);
    console.log('===============');
}

index.ts

import { AdadeltaOptimizer } from '@tensorflow/tfjs';
import "./extend";

const optimizer = new AdadeltaOptimizer(10, 10);

// the existing method is present
const className = optimizer.getClassName();

// the augmented method is also available
optimizer.newMethod(`The className is ${className}.`);

A comparable example can be found in the official TypeScript documentation here, which extends Observable with a map functionality.

Further Elaboration on Comments

Thank you for the insight. My concern lies in utilizing existing methods when defining newMethod within extend.ts rather than index.ts. Any suggestions on this?

It is achievable in extend.ts by accessing the original method like so:

import { AdadeltaOptimizer } from '@tensorflow/tfjs-core';

declare module '@tensorflow/tfjs-core' {
    interface AdadeltaOptimizer {
        newMethod(message: string): void;
    }
}

AdadeltaOptimizer.prototype.newMethod = function (message: string) {

    // simply access the original method through `this` 
    const className = this.getClassName();

    console.log('===============');
    console.log(className);
    console.log(message);
    console.log('===============');
}

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

Encountering an issue when attempting to host a Next.js application on Vercel

Why is it important to regularly do this task as per the instructions provided in the link? Info - Working on creating a highly efficient production build... Note: Next.js now collects completely anonymous telemetry data on user usage. This data helps sha ...

How can I attach a click event to the left border of a div using jQuery?

I am wondering about a div element <div id="preview"> </div> Can anyone suggest a method to attach a click event specifically to the left border of this div? Your help is greatly appreciated. ...

A widget for Windows 7 that can handle both HTTP GET and POST requests

I'm currently working on a small gadget for our intranet and have set up a PHP file on our server for initial testing purposes. Everything seems to be functioning properly when I use the GET request method, but I would prefer to utilize POST in order ...

Establishing a link between numerous web browsers solely through client-side technology

After creating a compact AJAX-powered chat application, I wonder if it is feasible to handle all the communication client-side. Can individual pages recognize each other and share real-time updates without involving the server? Is there a way to achieve th ...

I am interested in utilizing Sequelize, Vue, and Node to implement a query that filters data once it is retrieved to display on my view

Within my project, there's a table tracking user responses to a quiz. By utilizing the following query, I've successfully retrieved all the information from that table and stored it in my TotalQuizResponses array for display: this.totalQuizRespon ...

Unable to set initial values for Select Option in Redux-Form

I have implemented an update form using redux-form, where the form value is initialized using initialValues. For example: <DataEdit initialValues={ Data }/> The form in the DataEdit page looks like this: <Field name="Data.taxTitle" comp ...

VueJS is unable to access an array

Unable to access an array in Vue.js. console.log(this.ref_number_response[0]); When I try to access the array, it shows undefined. I'm puzzled by this... data(){ return{ ref_number_response: [], } }, methods:{ che ...

When will the javascript file fire if it has this implementation?

Can someone help me make sense of this jquery snippet? (function( window, undefined ) { //All the JQuery code is included here ... })(window); I'm curious, if a .js file is loaded in a page using the <script> tag, at what point does it ...

How can I trigger a success event in JavaScript after ASP.NET form validation?

Is there a way for me to be notified when my ASP.NET form validation is successful so I can subscribe to that event? Here's the situation: When a user clicks a button on a payment form, I want to display a message saying "processing," but only if the ...

How come Typescript allows me to generate intersection types that seem impossible?

Despite being unimplementable, the type definition below does not trigger any warnings from the compiler. // No type error type impossible = 0 & string[] & 'anything' An item cannot simultaneously be a number, a string[], and a stri ...

Enhancing a React modal to enable user input for updating state variables

Is there a way to utilize user input from the page to dynamically create elements in a React.js application? In my app.js file, I have defined some constants at the beginning for mock data: const book1 = [ {id: uuid(), content: 'reflections&apos ...

Trouble obtaining AJAX result using onClick event

As a newbie to AJAX, I am still trying to grasp the concept. My task involves using an AJAX call to extract specified information from an XML file. Even after carefully parsing all tag elements into my JavaScript code, I encounter a problem when attempting ...

Challenge with the submission event listener

I am struggling to create my first event listener for the submit button that should respond to both a click and an enter key press. Currently, it is not working for either event, and I am unsure why. I do not intend to send any data to another page; I simp ...

Having trouble with Vue.js not returning HTML elements from methods properly?

I have been attempting to retrieve html elements from a method, and I thought of using v-html for this purpose (not sure if there is a better approach). However, I seem to have encountered an issue with backtick templates and string interpolation. An error ...

Retrieve the previous route in Angular 7

I have developed a unique service that allows me to store route changes efficiently. import { Injectable } from '@angular/core'; import { Router, NavigationEnd } from '@angular/router'; @Injectable() export class RouteState { priva ...

Using the ternary operator in React to implement inline styles

Within my React/Typescript project, I aim to dynamically exhibit a color based on the presence or absence of a value in payload[1]. In the code snippet below, note the usage of an inline style tag. <li className="recharts-tooltip-item" style={ ...

What is the reason behind the restriction on using 'this' on the left side of an assignment?

Within the component class, I've been working on this: export class myapp { detail; myarr = ['me', 'myself', 'i']; title = this.myarr[0]; this.detail = this.title ; //error } I'm curious why `this.detail` ...

Discover the art of utilizing two distinct binding strings, wherein upon the selection of either, the alternate binding string shall automatically be

Having to use two different bindingstrings is a requirement due to a tool used for creating PDFs. My objective is to have the corresponding bindingstring turn "Off" when a user clicks on either the Yes or No button, and have the clicked button turn to "Yes ...

Utilizing Firebase objects across multiple files: A comprehensive guide

I apologize for my ignorance, but as I am teaching myself, I have not been able to find the answer in the available documentation. My current project involves developing a Vue application with Firebase as the backend. To utilize Firebase services, you mus ...

Can we trust the accuracy of Function.prototype.toString for our needs?

Can I trust Function.prototype.toString to provide a valid javascript function string for user-defined functions? Do any popular javascript engines differ in how they represent function objects as strings? I came across this question, but it doesn't ...