getelement javascript typescript

javascript - getelement - title css



Mecanografiado: clase de error extendido (4)

Estoy tratando de lanzar un error personalizado con mi nombre de clase "CustomError" impreso en la consola en lugar de "Error", sin éxito:

class CustomError extends Error { constructor(message: string) { super(`Lorem "${message}" ipsum dolor.`); this.name = ''CustomError''; } } throw new CustomError(''foo'');

La salida es Uncaught Error: Lorem "foo" ipsum dolor .

Lo que espero: Uncaught CustomError: Lorem "foo" ipsum dolor .

Me pregunto si eso se puede hacer solo con TS (sin jugar con los prototipos JS).


¿Está utilizando la versión 2.1 de mecanografiado y la transpilación a ES5? Consulte esta sección de la página de cambios importantes para ver posibles problemas y soluciones: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work

El bit relevante:

Como recomendación, puede ajustar manualmente el prototipo inmediatamente después de cualquier super (...) llamada.

class FooError extends Error { constructor(m: string) { super(m); // Set the prototype explicitly. Object.setPrototypeOf(this, FooError.prototype); } sayHello() { return "hello " + this.message; } }

Sin embargo, cualquier subclase de FooError tendrá que configurar manualmente el prototipo también. Para los tiempos de ejecución que no admiten Object.setPrototypeOf, en su lugar puede usar __proto__ .

Desafortunadamente, estas soluciones alternativas no funcionarán en Internet Explorer 10 y versiones anteriores. Uno puede copiar manualmente los métodos del prototipo en la instancia misma (es decir, FooError.prototype en esto), pero la cadena del prototipo en sí no se puede arreglar.


El problema es que el Error clase incorporado de Javascript rompe la cadena de prototipos al cambiar el objeto a construir (es decir, this ) a un objeto nuevo y diferente, cuando se llama super y ese nuevo objeto no tiene la cadena de prototipo esperada, es decir es una instancia de Error no de CustomError .

Este problema se puede resolver de forma elegante usando ''new.target'', que es compatible desde Typecript 2.2, consulte aquí: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html

class CustomError extends Error { constructor(message?: string) { // ''Error'' breaks prototype chain here super(message); // restore prototype chain const actualProto = new.target.prototype; if (Object.setPrototypeOf) { Object.setPrototypeOf(this, actualProto); } else { this.__proto__ = actualProto; } } }

Usar new.target tiene la ventaja de que no tiene que codificar el prototipo, como algunas otras respuestas aquí propuestas. Eso nuevamente tiene la ventaja de que las clases que heredan de CustomError también obtendrán automáticamente la cadena de prototipos correcta.

Si Object.setPrototype(this, CustomError.prototype) que codificar el prototipo (por ejemplo, Object.setPrototype(this, CustomError.prototype) ), CustomError sí tendría una cadena de prototipo funcional, pero cualquier clase que herede de CustomError se rompería, por ejemplo, las instancias de una class VeryCustomError < CustomError no ser instanceof VeryCustomError como se esperaba, pero solo instanceof CustomError .

Ver también: https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200


Funciona correctamente en ES2015 ( https://jsfiddle.net/x40n2gyr/ ). Lo más probable es que el problema sea que el compilador TypeScript se está transpilando a ES5, y Error no se puede subclasificar correctamente utilizando solo las funciones de ES5; solo se puede subclasificar correctamente utilizando ES2015 y características superiores ( class o, más oscuramente, Reflect.construct ). Esto se debe a que cuando llama a Error como una función (en lugar de a través de new o, en ES2015, super o Reflect.construct ), ignora this y crea un nuevo Error .

Probablemente tendrá que vivir con la salida imperfecta hasta que pueda apuntar a ES2015 o superior ...


Me encontré con el mismo problema en mi proyecto de mecanografía hace unos días. Para que funcione, utilizo la implementación de MDN usando solo vanilla js. Entonces su error sería similar al siguiente:

function CustomError(message) { this.name = ''CustomError''; this.message = message || ''Default Message''; this.stack = (new Error()).stack; } CustomError.prototype = Object.create(Error.prototype); CustomError.prototype.constructor = CustomError; throw new CustomError(''foo'');

No parece funcionar en el fragmento de código SO, pero funciona en la consola de Chrome y en mi proyecto de mecanografía: