Getting Started with TypeORM: A Beginners Guide

What is TypeORM?
TypeORM is an Object-Relational Mapping (ORM) library specifically designed for TypeScript and JavaScript frameworks. It allows developers to interact with databases using objects rather than traditional SQL queries. With TypeORM, you can simplify data management in your applications by leveraging interfaces, decorators, and other TypeScript benefits. It supports multiple database systems, including MySQL, PostgreSQL, SQLite, and Microsoft SQL Server, providing flexibility in deployment choices.
Why Choose TypeORM?
- TypeScript Support: TypeORM is built with TypeScript in mind. This ensures strong typing, allowing developers to catch errors during compile-time rather than runtime.
- Active Record and Data Mapper Patterns: Supports both patterns, offering various ways to organize your application logic according to your preferences.
- Migration Feature: TypeORM has a built-in migration system to manage database schema changes, making it easier to maintain your application’s database structure.
- Query Builder: Provides a powerful query building interface to create complex SQL queries using programmatic methods.
- Eager and Lazy Loading: Supports advanced loading strategies for related entities, promoting efficient data management.
Setting Up TypeORM
Step 1: Install Required Packages
To get started with TypeORM, you need to install it along with the database driver you plan to use. For example, if you’re using PostgreSQL, you’d execute the following command:
npm install typeorm reflect-metadata pgMake sure to also install TypeScript:
npm install typescript --save-devYou’ll also need to create a tsconfig.json file to configure TypeScript compilation settings. You can generate one with:
npx tsc --initAdjust the TypeScript configuration according to your needs.
Step 2: Create a Connection
TypeORM requires a database connection to function. Create a new file, ormconfig.ts, and add the following code to configure your database connection:
import { DataSource } from "typeorm";
export const AppDataSource = new DataSource({
type: "postgres", // Your database type
host: "localhost",
port: 5432, // PostgreSQL default port
username: "your_username",
password: "your_password",
database: "your_database",
synchronize: true, // Auto-sync models to the database
logging: false,
entities: [__dirname + "/entity/*.ts"], // Define the location of your entities
migrations: [__dirname + "/migration/*.ts"],
subscribers: [],
});Step 3: Create Your First Entity
Entities in TypeORM represent database tables. Create a new directory called entity and add a file named User.ts. Inside, define your entity like so:
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
@Column()
age: number;
}This code snippet defines a User entity with id, firstName, lastName, and age columns.
Step 4: Initialize the Connection
To utilize TypeORM, you must establish the connection defined earlier. Create an index.ts file and add the following code:
import "reflect-metadata";
import { AppDataSource } from "./ormconfig";
AppDataSource.initialize()
.then(() => {
console.log("Data Source has been initialized!");
// You can now perform database operations
})
.catch((err) => {
console.error("Error during Data Source initialization:", err);
});This code establishes a connection to the database and prints a success message to the console.
Working with Repositories
TypeORM introduces the concept of repositories, which provide an abstraction layer to interact with the database. Replace the content inside the then function with the following code to create, read, update, and delete users:
import { User } from "./entity/User";
// Create a new user
const createUser = async () => {
const userRepository = AppDataSource.getRepository(User);
const user = new User();
user.firstName = "John";
user.lastName = "Doe";
user.age = 25;
await userRepository.save(user);
console.log("User has been saved: ", user);
};
// Read users
const readUsers = async () => {
const userRepository = AppDataSource.getRepository(User);
const users = await userRepository.find();
console.log("Loaded users: ", users);
};
// Update a user
const updateUser = async (id: number) => {
const userRepository = AppDataSource.getRepository(User);
let user = await userRepository.findOneBy({ id });
if (user) {
user.age = 26;
await userRepository.save(user);
console.log("User updated: ", user);
}
};
// Delete a user
const deleteUser = async (id: number) => {
const userRepository = AppDataSource.getRepository(User);
await userRepository.delete(id);
console.log("User deleted with id: ", id);
};
// Call functions to test
createUser().then(() => {
readUsers();
});Migrations
For managing changes in your database schema, TypeORM allows you to create migrations. These are essential when working in a team environment or production setup.
To generate a migration, run the following CLI command:
npx typeorm migration:generate -n UserMigrationThis generates a migration file and you can adjust the up and down methods according to your schema changes. To run the migration, use:
npx typeorm migration:runQuery Builder
TypeORM also provides a powerful Query Builder for constructing complex SQL queries. For instance, to find users older than a certain age, you can use:
const usersAboveAge = await AppDataSource
.getRepository(User)
.createQueryBuilder("user")
.where("user.age > :age", { age: 20 })
.getMany();
console.log("Users older than 20: ", usersAboveAge);Error Handling
Building robust applications involves gracefully handling errors. Wrap your database operations in try-catch blocks:
try {
await createUser();
} catch (error) {
console.error("Failed to create user: ", error);
}Eager and Lazy Loading
When fetching related entities, you can opt for either eager or lazy loading. Eager loading retrieves related entities in the initial query:
const users = await userRepository.find({ relations: ["posts"] }); // Assuming User has a relation with PostIn contrast, lazy loading requires you to use a promise-like syntax:
const user = await userRepository.findOne({ where: { id } });
const posts = await user.posts; // Fetches the posts when accessedTesting
When developing applications, implementing tests is best practice. TypeORM can be tested using various JavaScript testing frameworks like Jest or Mocha. Mock the database connection for unit tests or use a separate database instance for integration tests.
Resources
To expand your knowledge of TypeORM, consider the following resources:
- Official Documentation: Comprehensive and regularly updated, the TypeORM documentation is your primary source for information.
- TypeORM GitHub Repository: In addition to code examples, the repository contains issues and discussions that can provide valuable insights.
- Community Forums and Stack Overflow: Engage with the TypeORM community for specific questions and experience sharing.
By following this guide, you’ll be well on your way to successfully implementing TypeORM in your projects. Understanding its core concepts will enable you to build efficient databases and web applications with ease.





