In a TypeScript web project I am using structuredClone
to deep-clone an AxiosError
object from the Axios library, defined as:
export interface AxiosError<T = any> extends Error {
//...
isAxiosError: boolean;
toJSON: () => object;
}
interface Error {
name: string;
// ...
}
My code:
function f(axiosError: AxiosError<ArrayBuffer>): void {
const copy = window.structuredClone(axiosError);
const a = typeof axiosError.name === "undefined"; // false
const b = typeof axiosError.isAxiosError === "undefined"; // false
const c = typeof copy.name === "undefined"; // false
const d = typeof copy.isAxiosError === "undefined"; // true
}
Upon further investigation, it appears that all of the parent properties are cloned, but the child properties are not. Why? I can reproduce this in Firefox and Chrome.
If you're asking why your sub-classed
AxiosError
only contains the default properties of the parentError
class, that's by design.structuredClone
is meant to be used to send data across realms. The receiving realm may have no clue about yourAwesomeError
class, and so the object is normalized to what all realms will know about, here anError
, but the same applies to other cloneable interfaces likeSet
,Map
etc.So indeed, if you stucture clone an instance of a subclass of
Error
, all you get are the default properties ofError
.Note that there is this issue which aims to at least make
.name
be treated exceptionally in the cloning algo, but it still requires implementers interest (read, "it's not done yet").