26

I am working in an angular 2 cli project in which I have to create a definition of a plugin, because it doesn't exists its typed. This plugin depends of a main library that has already its own typed and it works.

Anyway, I have two files the main one with

LIBRARY TYPES FILE A

export class A extends B {
    constructor(...);
    methodX(): void;
}

And I would need to add a new method for my plugin so my class would be like

export class A extends B {
        constructor(...);
        methodX(): void;
        methodY(): void;
    }

The point is that I need to add it in a separate file. The problem is adding a method to an existent class without creating a new one

If I put

PLUGIN TYPES FILE B

export class A extends B {
    constructor(...);
    methodX(): void;
}

or

PLUGIN TYPES FILE B

export class A extends B {
        constructor(...);
        methodX(): void;
        methodY(): void;
}

It doesn't work, does anyone how can I achieve overwriting a class or extending it with a new method that?

Thanks

4
  • Not sure from your question. It is not clear. Do you need Mixins? typescriptlang.org/docs/handbook/mixins.html Commented Mar 24, 2017 at 12:45
  • If you ask how "extending it", it is simple as class C extends A. But I think you mean "adding a new method without changing the class name". If that is right, please clarify your question. Commented Mar 24, 2017 at 12:47
  • 3
    also, why not just extend the class and add the method? Commented Mar 24, 2017 at 12:47
  • 1
    @toskv because sometimes you want to extend capabilities of a commonly used class. For example, adding flatMap to Array if you're using NodeJS < 11 (ts-node is Node in version 8). Commented Mar 19, 2019 at 11:36

3 Answers 3

32

The "Declaration Merging > Module Augmentation" section from the TypeScript docs seems to offer the solution:

https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation

In your case, if class A is exported from file1.ts, and you want to add methodY() to that class within a different module file2.ts, then try this:

//// file1.ts
export class A extends B {
    constructor(...);
    methodX(): void;
}

//// file2.ts
import { A } from "./file1";
declare module "./file1" {
    interface A {
        methodY(): void;
    }
}
A.prototype.methodY = function() {}
Sign up to request clarification or add additional context in comments.

3 Comments

Btw adding a new method to a class within the SAME file would have been done like so: class A {}; interface A { methodY(): void; }; A.prototype.methodY = function () {};
This is the one solution that actually worked! Thanks!
to add to the first comment, declare module './file1' still works inside of file1.ts You must do this for the compiler to understand your calls to methodY in other places. Read more here on Module Augmentation
19

You could do it by making an interface with the new method and modifying the prototype.

Something like this:

class B { }

class A extends B {
    constructor() {
        super();
    }
    methodX(): void { };
    methodY(): void { };
}


interface B {
    newMethod(): void;
}

B.prototype.newMethod = function () { console.log('a') };

This allows you do have proper typing when doing.

new A().newMethod();

I made a playground example here.

10 Comments

Do you need to use an interface? I added the function to the class itself, and it worked.
I had to add it otherwise the interface of B doesn't change and it wouldn't let me change the prototype of B.
it might depend where you make the change. in your example you do it inside the class itself. I do it from the outside. I think the OP wasn't allowed to change the code. :)
nope, it's not that.. I think it's just plnkr not complaining about it. :) It might have something to do with in browser compiler.
I didn't think he was asking to change interface B, but it makes sense to do it this way. My answer becomes unnecessary then, sorry for duplicate answer :)
|
3

You can do it directly as A.prototype.functionName = function(){...}

Here is a plunker: http://plnkr.co/edit/6KrhTCLTHw9wjMTSI7NH?p=preview

1 Comment

This should be the accepted answer. I've found in VSCode with typescript it won't accept the 'A.prototype.functionName' notation but will accept 'A.prototype["functionName"]'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.