Skip to main content

Entity

Connecting to the database is just the first step. To actually store and retrieve data, we need to define what our data looks like — its structure, column types, and constraints. In TypeORM, this is done through Entities.

What is an Entity?

An Entity is a TypeScript class decorated with @Entity(). Each instance of the class corresponds to a row in the database table. Each property of the class (decorated with @Column) corresponds to a column.

It is the TypeORM equivalent of a Mongoose Schema + Model combined into one.

MongooseTypeORM
new mongoose.Schema({ ... })Class properties + @Column()
mongoose.model('Name', schema)@Entity() on the class
Schema field optionsColumn decorator options

Creating an Entity

Here's a simple entity for a Person:

src/entities/Person.ts
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
} from "typeorm";

@Entity()
export class Person {
@PrimaryGeneratedColumn()
id: number;

@Column()
name: string;

@Column()
age: number;

@Column({ unique: true })
email: string;

@CreateDateColumn()
createdAt: Date;
}

Let's break it down:

  • @Entity(): Tells TypeORM this class is a database table. The table name defaults to the class name in lowercase (person). You can override it: @Entity("people").
  • @PrimaryGeneratedColumn(): Creates an auto-incrementing integer primary key column called id. This is analogous to MongoDB's _id.
  • @Column(): Marks a class property as a table column. TypeORM infers the column type from the TypeScript type (stringvarchar, numberinteger, booleanboolean).
  • @CreateDateColumn(): Automatically sets the column to the current timestamp when a row is inserted. TypeORM also provides @UpdateDateColumn() for automatic update timestamps.

Column Options

You can pass an options object to @Column() to configure the column:

@Column({ type: "varchar", length: 100, nullable: false, default: "Unknown" })
name: string;
OptionDescriptionExample
typeThe database column type. Usually inferred automatically."varchar", "int", "text"
lengthMax length for string columns.length: 255
nullableWhether the column allows NULL. Defaults to false.nullable: true
uniqueAdds a unique constraint to the column.unique: true
defaultDefault value if none is provided.default: "Pakistan"
selectIf false, the column is excluded from SELECT queries.select: false (useful for passwords)
enumRestricts the column to a set of allowed string values.enum: ["male", "female"]

Column Types

TypeORM infers the SQL type from the TypeScript type automatically in most cases. Here's a reference:

TypeScript TypeInferred SQL Type
stringvarchar
numberinteger
booleanboolean
Datetimestamp
string[]simple-array

For full control, pass the type explicitly:

@Column({ type: "text" })
bio: string;

@Column({ type: "decimal", precision: 10, scale: 2 })
price: number;

@Column({ type: "enum", enum: ["admin", "user", "guest"], default: "user" })
role: string;

Special Column Decorators

DecoratorPurpose
@PrimaryGeneratedColumn()Auto-incrementing integer primary key
@PrimaryGeneratedColumn("uuid")UUID primary key (automatically generated)
@CreateDateColumn()Set to NOW() on insert, never updated
@UpdateDateColumn()Set to NOW() on every update
@DeleteDateColumn()Enables soft deletes — stores deletion timestamp
@VersionColumn()Auto-increments on each update (optimistic locking)

Nullable Columns

By default, TypeORM marks columns as NOT NULL. If a column is optional, mark it as nullable:

@Column({ nullable: true })
phone: string | null;

A Complete Entity Example

src/entities/Person.ts
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
} from "typeorm";

@Entity("people")
export class Person {
@PrimaryGeneratedColumn()
id: number;

@Column({ length: 100 })
name: string;

@Column()
age: number;

@Column({ unique: true })
email: string;

@Column({ nullable: true })
phone: string | null;

@Column({ default: true })
isAlive: boolean;

@Column({ type: "enum", enum: ["male", "female", "other"] })
gender: string;

@Column({ select: false })
password: string;

@CreateDateColumn()
createdAt: Date;

@UpdateDateColumn()
updatedAt: Date;
}

Relations Between Entities

Just like Mongoose uses ref to link documents, TypeORM uses relation decorators to link entities. These become foreign key columns in the database.

ManyToOne / OneToMany

A post belongs to one user. A user can have many posts.

src/entities/User.ts
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm";
import { Post } from "./Post";

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;

@Column()
name: string;

@OneToMany(() => Post, (post) => post.author)
posts: Post[];
}
src/entities/Post.ts
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm";
import { User } from "./User";

@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;

@Column()
title: string;

@ManyToOne(() => User, (user) => user.posts)
author: User;
}

TypeORM will automatically add an authorId foreign key column to the post table.

tip

@OneToMany is always defined alongside a matching @ManyToOne on the other side. The table that holds the foreign key column is always the @ManyToOne side.

Registering the Entity

Make sure your entity file matches the glob pattern in your DataSource configuration:

src/data-source.ts
entities: ["src/entities/*.ts"],

With synchronize: true enabled, TypeORM will automatically create the table when the app starts.

Conclusion

In this doc, we learned how to define an Entity in TypeORM using decorators. An Entity maps a TypeScript class to a PostgreSQL table. We covered column types, options, special decorators, and how to define relations between entities.

In the next doc, we'll learn how to perform CRUD operations using the Repository API.