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: