class-transformer: mapping plain JSON into typed TypeScript classes
Decorator-based transformation, serialization, and deserialization between objects and classes.
At a glance
- What is it?
- typestack/class-transformer turns the plain objects you get from JSON.parse into real instances of your classes, and controls what those classes expose. It is decorator-driven, and it depends on reflect-metadata.
- Who is it for?
- Adopt class-transformer when you already model your data as TypeScript classes and need JSON.parse output to carry methods, declared types and a controlled serialization shape, particularly inside a NestJS app where the dependency is already present.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 133 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap between JSON.parse output and a real User instance
JavaScript gives you two kinds of objects. Plain objects, created with `{}` or returned by `JSON.parse`, are instances of Object. Class objects come from a constructor and carry their own properties and methods. The README frames the entire problem around that split: after you parse a users.json payload you can read `users[0].id` and `users[0].firstName`, but `users[0].getName()` fails, because the array holds plain objects. TypeScript lets you write `fetch('users.json').then((users: User[]) => ...)` and the compiler believes you, which the README calls lying to the compiler. The library exists to close that gap by constructing real instances and copying the properties across. The audience is TypeScript and ES6 codebases on both frontend and backend, and the README explicitly points at API models as a second use case, where you want control over which fields leave your service. If your data never needs behaviour or a declared shape, this is overhead you do not need.
How transformation actually runs: decorators, metadata, and the transform pipeline
The mechanism rests on reflect-metadata. Decorators such as @Expose, @Exclude, @Type and @Transform write metadata onto the class, and the transformation functions read that metadata when they walk your object. That is why the README lists reflect-metadata as a required shim rather than an optional peer: without it the decorators have nowhere to record their intent and the library cannot know which class a nested property should become. A call like plainToInstance(User, users) takes the target class and the plain source, creates instances, and maps properties according to the metadata. The reverse direction, instanceToPlain, applies the same metadata to decide which properties survive serialization. Groups and versioning add a second axis: @Expose({ groups: [...] }) and @Expose({ since: ..., until: ... }) let one class produce different shapes for different callers, which is the feature that makes the library interesting for API models rather than just a constructor wrapper. The README also documents circular reference handling and implicit type conversion as separate concerns, and both are behaviours you should read about before assuming the defaults match your data.
Installing class-transformer and a first plainToInstance call
The README's Node.js path is two packages, the library and the metadata shim. Install both with --save as the README shows.
npm install class-transformer --save
npm install reflect-metadata --saveThen import the shim once in a global entry point, such as app.ts. The README is explicit that this import must happen before anything reads the metadata.
import 'reflect-metadata';With that in place, a class with a method and a plain array from JSON can be joined. The README's own example fetches users.json and passes the parsed array to plainToInstance.
import { plainToInstance } from 'class-transformer';
fetch('users.json').then((users: Object[]) => {
const realUsers = plainToInstance(User, users);
// each entry is now an instance of User
});After this call, `realUsers[0].getName()` and `realUsers[0].isAdult()` work, because the entries are instances of User rather than plain objects. For a browser build the README instead asks you to add a script tag pointing at node_modules/reflect-metadata/Reflect.js in the head of index.html. Nested objects need @Type on the property, otherwise the nested value stays plain.
Where class-transformer stops: validation, and nested types it cannot infer
The clearest limitation is signposted by the README itself. There is a section titled enforcing type-safe instance, and the answer it gives is class-validator. plainToInstance performs transformation, not validation. It will build a User from an object whose age is a string or missing entirely, and the resulting instance is still an instance of User. If your input comes from outside your trust boundary, transformation alone is the wrong tool. The second limitation is nested typing. TypeScript erases generics and property types at runtime, so the library cannot know that a property declared as Address should be built from Address. You must decorate nested properties with @Type, and the README has a whole section on providing more than one type option, which implies the simple case is not always enough. Arrays of unions and polymorphic payloads push you toward explicit discriminator logic. Third, the decorator approach ties you to a toolchain that emits metadata; the README does not document a runtime fallback for environments where that is unavailable.
class-transformer versus zod, and versus hand-written mappers
The related searches keep returning to alternatives, and the honest comparison is with schema-validation libraries such as zod. The two solve overlapping but different halves of the problem. class-transformer starts from the class as the source of truth and uses decorators to describe how a plain object becomes an instance and how that instance serializes back. zod starts from a schema value and derives both a validator and a static TypeScript type from it, so parsing and checking happen in one step and a failed check is a first-class outcome. With class-transformer, checking is a separate library and a separate pass. The other alternative is a hand-written mapper: a factory function or a static fromJSON on each class. That has no dependencies, no metadata requirement and no decorator syntax, and for a handful of shallow models it is genuinely less machinery. It becomes painful exactly where class-transformer earns its place: deep hierarchies, per-caller field visibility and versioned API shapes, which is the case the README's groups and versioning sections target.
Maintenance, release cadence and what the MIT licence leaves you
The repository is not archived, and the last push was on 2026-05-22, so the develop branch is being touched. The release history tells a different story: the newest listed release is v0.5.1 from 2021-11-22, with v0.5.0 and v0.4.1 two days earlier. That is a wide gap between commits and tagged releases, and it matters for upgrade planning. If you pin class-transformer, expect to track the develop branch or a commit rather than a steady stream of published versions, and read CHANGELOG.md before moving. The package.json shows the build split into cjs, esm5, esm2015 and types outputs, with test, lint:check and prettier:check scripts, so the project has a real build and test pipeline even without frequent releases. The licence is MIT, which is permissive and imposes no copyleft obligation on your application; the LICENSE file sits at the repository root. This is not legal advice, and if you redistribute the library itself you should read the licence text rather than rely on this summary.
Editorial conclusion
Adopt class-transformer when you already model your data as TypeScript classes and need JSON.parse output to carry methods, declared types and a controlled serialization shape, particularly inside a NestJS app where the dependency is already present. Do not adopt it if you want runtime validation of untrusted input: the README's own section on enforcing a type-safe instance points to class-validator for that, and plainToInstance will happily produce an instance whose fields are undefined. Before committing, verify three things in your own codebase: that reflect-metadata is imported once at a global entry point, that every nested property has an explicit @Type decorator, and that your build toolchain can emit decorator metadata, since the library is decorator-based and the README gives no fallback path when metadata is unavailable. The install itself is two npm packages, class-transformer and reflect-metadata, and the API surface is small enough to read end to end.
Frequently asked questions
What is class-transformer used for?
It converts plain JavaScript objects, such as the result of JSON.parse, into instances of the classes you have defined, and converts instances back to plain objects for serialization. The README also presents it as tooling for controlling which properties your API models expose.
How does class-transformer compare to zod?
class-transformer is decorator-based and starts from your class, transforming a plain object into an instance while reading metadata written by decorators like @Expose and @Type. zod is schema-first and combines validation with type derivation in a single parse step. The README points to class-validator, not zod, for enforcing a type-safe instance.
What are the alternatives to class-transformer for TypeScript?
Two realistic options are a schema-validation library such as zod, which validates and types in one pass, and hand-written mapper functions or static fromJSON methods on each class, which need no metadata shim and no decorators. The hand-written route holds up for shallow models and gets expensive with nested hierarchies and per-caller field visibility.
Is class-transformer used with NestJS?
The README does not mention NestJS, so nothing about that integration can be confirmed from the project's own documentation. The library is published on npm as class-transformer and its README describes use on both frontend and backend, which is the scope it claims.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/typestack-class-transformer)