typescript - Problema al añadir un nuevo método al prototipo de Promise
typescript 3.1.2
He buscado en muchas preguntas de Stack Overflow y en artículos en línea, y he visto los mismos tipos de respuestas muchas veces a preguntas sobre cómo modificar clases existentes de TypeScript como String y Array<T>, pero no puedo lograr que esto funcione para la clase Promise<T>.
Ya he leído todo esto, sin suerte:
¿Cómo definir una función global en TypeScript?
Cómo agregar un archivo con extensión de prototipo en Typescript
¿Cómo extender el prototipo de String y usarlo después en Typescript?
El comando personalizado de TypeScript de Cypress no es una función
Extender Array en TypeScript
Aquí está mi código actual (he probado muchas variantes):
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}`);
}]);
}
(He intentado agregar export { } en Promise.ts, no ayuda)
otro.ts
import '../theDir/Promise'
anAsyncMethod().catchWrapper();
Todo esto se compila, pero continuamente obtengo errores en tiempo de ejecución:
UnhandledPromiseRejectionWarning: TypeError: anAsyncMethod().catchWrapper is not a function¿Mi implementación de catchWrapper() no está siendo coincidente con la declaración de la interfaz por el compilador?
¿Alguna idea de cómo solucionar esto?
Respuesta #1
El objetivo aquí era tener el método de extensión en una biblioteca y usarlo en otras aplicaciones. Después de experimentar con ello durante un tiempo, terminé usando esta solución. Omitir cualquier parte de ella causa errores en tiempo de ejecución.
Al colocar tanto la declaración como la definición en el archivo .ts y luego importar el archivo (¡en cualquier lugar!) en la lib, mi otro proyecto puede usar el método de extensión tan pronto como importe cualquier cosa de la lib.
Aquí está cómo se ve el código final:
En el proyecto lib:
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'
En la aplicación principal:
// 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*/ }`
Respuesta #2
Intenta cambiar el contenido o Promise.d.ts a esto:
declare interface Promise<T> {
catchWrapper (): Promise<T>;
}
Tampoco debería ser necesario importar el .d.ts si se encuentra ya sea en tu rootDir o en uno de los typeRoots especificados en el archivo de configuración.
