Blog
Wild & Free Tools

JSON to TypeScript Class vs Interface — Which to Generate

Last updated: March 2026 6 min read
Quick Answer

Table of Contents

  1. Interface Is Usually the Answer
  2. When You Actually Want a Class
  3. Converting Interface to Class
  4. Runtime Behavior Differences
  5. TypeScript Type vs Interface vs Class
  6. Frequently Asked Questions

Plenty of people search for "JSON to TypeScript class" and end up with an interface generator. For almost every use case that's the right outcome — interfaces are lighter, compile away to nothing, and do the same job for data shapes. Here's when a class is actually the right tool and how to turn an interface into one.

Interface Is Usually the Answer

For plain data shapes — API responses, configuration objects, form payloads, DTOs — an interface gives you:

Classes add:

For JSON-derived shapes, you rarely need any of the extras. The data came in as JSON; it has no methods attached. Wrapping it in a class just for type safety is overhead.

When a Class Earns Its Keep

Three legitimate reasons to generate a class instead of an interface:

1. Decorator-based validation (NestJS, class-validator). NestJS's request validation system reads decorators like @IsEmail() and @MinLength() off class fields. Interfaces can't carry decorators. If you're building a NestJS API, DTOs are classes.

2. ORM models (TypeORM, MikroORM). Entity classes with @Entity(), @Column(), and relationship decorators. Again, class-only.

3. Genuine methods on the shape. A User class with fullName(), isAdmin(), or other computed accessors that travel with the data.

If none of those apply, interface is the right call. Check these three cases first before reaching for a class.

Sell Custom Apparel — We Handle Printing & Free Shipping

Generating Interface First, Wrapping as Class

Our tool generates interfaces. If you need a class, generate the interface and wrap it:

// Generated:
interface User {
  id: number;
  email: string;
  displayName: string;
}

// Wrapped as class:
class User {
  id: number;
  email: string;
  displayName: string;

  constructor(data: User) {
    this.id = data.id;
    this.email = data.email;
    this.displayName = data.displayName;
  }

  get initials(): string {
    return this.displayName.split(' ').map(n => n[0]).join('');
  }
}

Note the interface and class can coexist with the same name — TypeScript's declaration merging means new User(data) works and user: User types correctly.

For NestJS DTOs specifically, skip the interface middle step and declare the class directly with decorators. The interface won't add anything.

Runtime Behavior Differences

This is the part people miss. An interface is compile-time only:

// TypeScript:
interface User { id: number; name: string; }
const u: User = { id: 1, name: 'x' };

// After compilation, the interface is gone:
const u = { id: 1, name: 'x' };

A class stays in the runtime:

class User { id = 0; name = ''; }
const u = new User();

// After compilation:
class User { constructor() { this.id = 0; this.name = ''; } }
const u = new User();

Real consequence: you can do u instanceof User with a class. You cannot with an interface. If your code path depends on distinguishing "is this really a User" at runtime, you need a class.

For JSON that's parsed from an API response — const u = response.data; — that's a plain object, not an instance of any class. u instanceof User is false even if it matches the shape. Class-based type guards need an explicit rehydration step.

The Full Picture — Type vs Interface vs Class

Featuretype aliasinterfaceclass
Describes a shapeYesYesYes
Runtime presenceNoNoYes
Can be instantiatedNoNoYes (new)
Supports methodsIn object typeIn object typeYes, with this
Supports decoratorsNoNoYes
Supports union typesYesNoNo
Declaration mergingNoYesNo
instanceof checksNoNoYes

The practical decision tree: need decorators? class. Need runtime identity? class. Need a union? type. Everything else: interface.

Generate Your Interface

Paste JSON, get a TypeScript interface. Wrap as a class only when you need one.

Open Free JSON to TypeScript Generator

Frequently Asked Questions

Does your tool generate classes?

No, interfaces only. Wrap the interface in a class if you need one — it is a ~10-line addition once you have the field list.

Why don't interfaces show up as a class instance?

Interfaces compile away. A plain object matching an interface is not "an instance" of anything — you need a class for instanceof checks.

Is there a performance difference between class and interface?

Interfaces have zero runtime cost. Classes have method lookup overhead on access. For most apps the difference is irrelevant; for hot paths interfaces win.

Can I use class-validator decorators with an interface?

No. Decorators need a class. For NestJS validation DTOs, declare the class directly with decorators on each field.

Stephanie Ward
Stephanie Ward Diagram & Visual Documentation Writer

Stephanie spent eight years as a business analyst creating flowcharts and process diagrams for enterprise software teams.

More articles by Stephanie →
Launch Your Own Clothing Brand — No Inventory, No Risk