Understanding JSON → TypeORM
Decorators, classes, and a repository.
Why TypeORM looks like Hibernate translated to TypeScript, and where it sits among the modern ORM choices.
Active record meets data mapper.
TypeORM offers two patterns. Active record — entity classes have methods like save(), remove() — feels like Ruby on Rails. Data mapper — a separate Repository<User> handles persistence — feels like Hibernate / Doctrine. The same entity class works with either pattern; pick the one that fits your project's style. Modern codebases tend toward data mapper for testability.
Decorators do the schema.
Every column, primary key, relation and index is a decorator on a class property. @Entity() marks the class as a table; @PrimaryGeneratedColumn() gives you an auto-increment id; @Column() with options handles the rest; @OneToMany / @ManyToOne wire relations. The experimental decorators feature is required in tsconfig.json — experimentalDecorators: true plus emitDecoratorMetadata: true.
A worked example.
From { "id": 7, "email": "a@b.com", "name": "Q", "createdAt": "2026-..." }: import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn } from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id!: number;
@Column({ unique: true })
email!: string;
@Column()
name!: string;
@CreateDateColumn()
createdAt!: Date;
} @CreateDateColumn is the convention shortcut for "set this to the current timestamp on insert"; the underlying SQL is DEFAULT CURRENT_TIMESTAMP.
Decorator equivalents
@PrimaryGeneratedColumn, @CreateDateColumn
Conventional shortcuts replace verbose @Column option blocks.
Each decorator declares table column + type + default
= Migration-ready entity
Relations need both sides.
A @ManyToOne on the child entity needs a matching @OneToMany on the parent. TypeORM uses both sides to generate the right SQL and to enable eager / lazy loading. Forgetting the inverse side is a common bug: the relation works for one direction and silently fails for the other. Codegen tools that detect a nested object should emit both sides.
Migrations are explicit.
Unlike Prisma's migration auto-generation, TypeORM offers two modes: synchronize: true (the schema auto-updates on app start — for development only) and explicit migrations generated with typeorm migration:generate. Production deployments must use the explicit form; synchronize on prod has lost real data more than once. The inferred entity is the starting point; the migration captures the diff.
TypeORM vs the alternatives.
TypeORM is the right choice for projects that came from a Java/Hibernate or Doctrine background and want a familiar style. It's a worse choice for greenfield TS projects in 2026 — Drizzle is closer to SQL, Prisma is closer to ergonomic ORMs, both have more momentum. TypeORM's metadata-reflection mechanism has had recurring rough edges and the project's maintenance pace has been uneven. Still shippable, still maintained; just no longer the default.