Mat Bess
Mat Bess

Reputation: 141

Problem adding a new method to Promise prototype

typescript 3.1.2

I have searched through many stack overflow questions and online articles, and I've seen the same types of answers many times to questions about modifying existing typescript classes such as String and Array<T>, but I can't seem to get this working for the Promise<T> class.

I've already read through all of these, no luck:

How to define global function in TypeScript?

How to add file with extending prototype in Typescript

How to extend String Prototype and use it next, in Typescript?

Cypress Custom TypeScript Command is not a Function

Extending Array in TypeScript


Here's my current code (I've tried many variations):

Promise.d.ts

declare global {
    export interface Promise<T> {
        catchWrapper(): Promise<T>;
    }
}

Promise.ts

Promise.prototype.catchWrapper = function<T>(this: Promise<T>): Promise<T> {
    return Promise.prototype.catch.apply(this, [e => {
        console.log(`catch wrapper. ${e}`);
        }]);
    }

(I've tried adding export { } in Promise.ts, it doesn't help)

another.ts

import '../theDir/Promise'

anAsyncMethod().catchWrapper();

This all compiles but I continually get runtime errors:

UnhandledPromiseRejectionWarning: TypeError: anAsyncMethod().catchWrapper is not a function

Is my implementation of catchWrapper() not being matched up to the declaration of the interface by the compiler?

Any ideas on how to fix this?

Upvotes: 2

Views: 1199

Answers (2)

Mat Bess
Mat Bess

Reputation: 141

The goal here was to have the extension method in a lib and use it in other apps. After messing around with it for a while I ended up using this solution. Leaving any part of it out causes runtime errors.

By putting both the declaration and definition in the .ts file and then importing the file (anywhere..!) in the lib my other project is then able to use the extension method as soon as it imports anything from the lib.

Here's what the final code looks like:

In the lib project:

Promise.ts

Promise.prototype.catchExtension = function<T>(this : Promise<T>): Promise<T> {
    return Promise.prototype.catch.apply(this, [() => { /*do stuff*/ }]);
}

declare global {
    interface Promise<T> {
        catchExtension(): Promise<T>;
    }
}
export { }

lib.ts

import './Promise';
export { } from './Promise';
// The rest of the exports
export { Example } from './Example'

In the main app:

// Import anything from lib
import { Example } from '@mylib'
// import { } from '@mylib' <--- doesn't work

const x: Promise<string> = new Promise( (resolve, reject) => { reject(); });
x.catchExtension();
// It works! We end up in `() => { /*do stuff*/ }`

Upvotes: 3

Dmitriy
Dmitriy

Reputation: 2822

Try changing the content or Promise.d.ts to this:

declare interface Promise<T> {
  catchWrapper (): Promise<T>;
}

Also should not need to import the .d.ts if it is located either in your rootDir or in one of typeRoots specified in the config file.

Upvotes: 1

Related Questions