Search code examples
jsontypescriptclassencapsulationprotected

How to ignore protected readonly member of class during serialization


Suppose I have a class in Typescript with a protected readonly member that's a constructor argument, and multiple classes that extend from the class and use that property:

class Yolo {
    public readonly swolo: boolean = false;
    // Lots of other properties

    constructor(protected readonly swag: string = '') {}
}

and I want the string that results from JSON.stringify(new Yolo()) to not have any swag:

{"swolo":false, ...(Every other property except "swag")}

Is there a way to accomplish this by exclusion (i.e., not using a second parameter on JSON.stringify) because there are many other properties on the class, and still retain Intellisense?

My initial inclination was to write toJSON as something like

public toJSON() {
    const serializableEntries: {
        -readonly [K in keyof Yolo]: Yolo[K]
    } = {
        ...this
    };

    delete serializableEntries.swag;
    return serializableEntries;
}

but that results in a compilation error because keyof Yolo doesn't include swag:

Property 'swag' does not exist on type '{ toJSON: () => string; }'.

I've considered the following workarounds:

  1. I could cast to any in toJSON
  2. I could remove the readonly modifier from the Class declaration and remove the type declaration on serializableEntries in toJSON
  3. I could make swag public

but none of those options are favorable in my opinion. I would like to keep Intellisense and the access modifiers as-is. Is it even possible?


Solution

  • How about using object destructuring:

    public toJSON(): string {
        const { swag: _, ...props } = this;
        return JSON.stringify(props);
    }
    

    That has the effect of copying all properties of this into props except for the swag property.

    console.log(new Yolo("shwag").toJSON()); //{"swolo":false}
    

    Looks good to me. Hope that helps; good luck!

    Link to code