npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

class-hydrator

v1.0.13

Published

Transformation typescript class instance to stringifiable(serializable) plain object

Readme

#class-hydrator

When you stringify an instance of a typescript class, it loses its class type and it's impossible to use methods of it. And you can't even stringify it if the instance had circular structures.

Introduce class-hydrator. dehydrate the instance and stringify it. And send it with ajax, websocket, webrtc to remote machine. Then, hydrate (restore) it and use it as if it was created in remote machine.

This is my first open-source project for my private project. I hope it also helpful for your projects. Forks, pull-requests and feedbacks are always welcome.

##Installation

  1. It supports only a typescript project. And it requires emitDecoratorMetadata, experimentalDecorators options in tsconfig.json
    {
      "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "moduleResolution": "node",
        "sourceMap": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "removeComments": false,
        "noImplicitAny": false,
        "suppressImplicitAnyIndexErrors": true
      }
    }
  2. Install it with npm
    $npm install --save class-hydrator

##Getting started

Let's create some classes like below.

class Seed {
  fruit:Fruit;
  harvest(){
    return this.fruit;
  }
}

class Strawberry {
  constructor(public weight:number, public seed:Seed){
    seed.fruit = this;    // causes circular structure!
  }
  greeting(){ console.log("Hi, I'm a strawberry") }
  getSeed(){ return this.seed }
}

And create strawberry instance using classes defined above.

let strawberry = new Strawberry(30, new Seed());

You cannot serialize strawberry as it is. JSON.stringify(strawberry) will throw an Error because strawberry instance has a circular structure. So, dehydrate it before serializing.

import { Hydrator, hydrate, dehydrate, serialize } from "class-hydrator";

let dehydratedStrawberry = Hydrator.dehydrate(strawberry);  // little verbose
// or you can also
let dehydratedStrawberry = dehydrate(strawberry);           // dehydrate is same with Hydrator.dehydrate except there is no namespace.
                                                // Which style you choose is entirely up to your favor.
/* dehydratedStrawberry
  Object{
    _c_: "Strawberry", _i_: 0,
    weight: 30,
    seed: Object{
      _c_: "Seed", _i_: 1,
      fruit: "_i_0"
    }
  }
 */
let serializedStrawberry = JSON.stringify(dehydratedStrawberry);

or you can just

let serializedStrawberry = serialize(strawberry);

And now, suppose that serializedStrawberry have sent to remote browser using websocket or xhr or anything you prefer. Remote browser can hydrate (restore) it preserving class types and circular structures. Before hydrating it, Every classes in Strawberry should have been provided to Hydrator so as to use the classes for instantiating in hydrating process..

import { Hydrator, hydrate, deserialize } from "class-hydrator";

Hydrator.provideClasses([Strawberry, Seed]);
dehydratedStrawberry = JSON.parse(serializedStrawberry);
restoredStrawberry = hydrate(dehydratedStrawberry, Strawberry);

or you can just

restoredStrawberry = deserialize(serializedStrawberry, Strawberry);

You can now use restoredStrawberry.greeting() or restoredStrawberry.seed.harvest().

##Decorators You can refine how the properties in you Class will be Hydrated or Dehydrated with property decorators. I prepared two decorators, @OnDehydrate() and @OnHydrate(). And also additional @Exclude() for convenience.

import {Hydrator, OnHydrate, OnDehydrate, hydrate, dehydrate} from 'class-hydrator';

class Point{
  constructor(public x:number, public y:number){ }
}

class Rectangle{
  @OnDehydrate((self)=>{    // or you can use just @Exclude() (@Exclude() equals to @OnDehydrate((self)=>null)
    return null;
  })
  @OnHydrate((self)=>{
    let divElement = new HTMLDivElement();
    // style the divElement using self.color, self.offset
    return divElement;
  })
  elem:HTMLDivElement;
  
  constructor(private color:string, private offset:Point){ }
}

Hydrator.provideClasses([Point, Rectangle]);

@OnDehydrate() decorator accepts a function which returns new value you want to set when Rectangle is dehydrated. It is good practice to compress some properties if they can be generated using other properties. Rectangle.elem will be null when you dehydrate a Rectangle-type object. And restored when being hydrated.

You can hydrate Rectangle instance as well as dehydrated Rectangle so as to trigger the @OnHydrate() decorators.

let rectangle = new Rectangle('red', new Point(300,200)); // rectangle.elem is not ready yet.
rectangle = hydrate(rectangle);                           // rectangle.elem is now ready.