TypeORM

TypeORM - data-mapper ORM for TypeScript and JavaScript (ES7, ES6, ES5). Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, WebSQL databases. Works in Node.JS and Browser.

Tables and Columns

Table decorators

There are several types of table decorators in TypeORM:

Entity options


export interface EntityOptions {

    /**
     * Specifies a default order by used for queries from this table when no explicit order by is specified.
     */
    readonly orderBy?: OrderByCondition|((object: any) => OrderByCondition|any);

    /**
     * Table's database engine type (like "InnoDB", "MyISAM", etc).
     * Note that it used only during table creation.
     * If you update this value and table is already created, it will not change table's engine type.
     */
    readonly engine?: string;

}
        

Column decorators

There are several types of column decorators in TypeORM:

Column options


export interface ColumnOptions {

    /**
     * Column type. More about column types described in next section.
     */
    readonly type?: ColumnType;

    /**
     * Column name in the database.
     */
    readonly name?: string;

    /**
     * Column type's length. Used only on some column types.
     * For example type = "string" and length = "100" means that ORM will create a column with type varchar(100).
     */
    readonly length?: string;

    /**
     * Indicates if this column is PRIMARY.
     * Same can be achieved if @PrimaryColumn decorator will be used.
     */
    readonly primary?: boolean;

    /**
     * Specifies if this column will use auto increment (sequence, generated identity).
     * Note that only one column in entity can be marked as generated, and it must be a primary column.
     */
    readonly generated?: boolean;

    /**
     * Specifies if column's value must be unique or not.
     */
    readonly unique?: boolean;

    /**
     * Indicates if column's value can be set to NULL.
     */
    readonly nullable?: boolean;

    /**
     * Default database value.
     */
    readonly default?: any;

    /**
     * The precision for a decimal (exact numeric) column (applies only for decimal column), which is the maximum
     * number of digits that are stored for the values.
     */
    readonly precision?: number;

    /**
     * The scale for a decimal (exact numeric) column (applies only for decimal column), which represents the number
     * of digits to the right of the decimal point and must not be greater than precision.
     */
    readonly scale?: number;

    /**
     * Indicates if this date column will contain a timezone.
     * Used only for date-typed column types.
     * Note that timezone option is not supported by all databases (only postgres for now).
     */
    readonly timezone?: boolean;

}
        

Column types

Embeddable tables and @Embedded decorator

Sometimes in your app you have object that contains another object, but you don't want to create separate tables in your app for them. You only want to create a single table and storage all from both objects in a single table. To achieve that mark your secondary entity, that should be merged into primary entity with @EmbeddableEntity decorator:


import {Entity, Column} from "typeorm";

@EmbeddableEntity()
export class PhotoMetadata {

    @Column("int")
    height: number;

    @Column("int")
    width: number;

    @Column()
    orientation: string;

    @Column()
    compressed: boolean;

    @Column()
    comment: string;

}
        

Add object relation in your main object and mark it with Embedded decorator:


import {Entity, Column, PrimaryGeneratedColumn} from "typeorm";
import {PhotoMetadata} from "./PhotoMetadata";

@Entity()
export class Photo {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @Column()
    description: string;

    @Column()
    fileName: string;

    @Embedded(type => PhotoMetadata)
    metadata: PhotoMetadata;
}
        

That's all, now you can create and persist photo object with photo metadata inside, and all the data will be saved into a single table.

Tree tables

TypeORM supports Adjacency list and Closure table patterns of storing tree structures.

Adjacency list

Adjacency list is a simple model with self-referencing. Benefit of this approach is simplicity, drawback is that you can't load big tree an once because of joins limitation. Let's create an example:


import {Entity, Column, PrimaryGeneratedColumn, ManyToOne} from "typeorm";

@Entity()
export class Category {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @Column()
    description: string;

    @OneToMany(type => Category, category => category.children)
    parent: Category;

    @ManyToOne(type => Category, category => category.parent)
    children: Category;
}
        

Closure table

Closure table stores relations between parent and child in a separate table in a special way. Its efficient in both reads and writes. To learn more about closure table take a look at this awesome presentation by Bill Karwin. Lets refactor our category example to use closure table:


import {ClosureEntity, Column, PrimaryGeneratedColumn, ManyToOne} from "typeorm";

@ClosureEntity()
export class Category {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @Column()
    description: string;

    @TreeChildren({ cascadeAll: true })
    children: Category;

    @TreeParent()
    parent: Category;

    @TreeLevelColumn()
    level: number;
}
        

With closure table you can use TreeRepository with special methods to work with trees. You can access tree repository via connection connection.getTreeRepository(Category).

In the future versions TypeORM will support materialized path and nested set patterns.

Table inheritance

TypeORM supports Concrete table inheritance, Single table inheritance and Class table inheritance patterns of storing inherited data.

Concrete table inheritance

Concrete table inheritance is possible through the child classes decorated with @AbstractEntity decorator. Example:


import {AbstractEntity, Column, PrimaryGeneratedColumn} from "typeorm";

@AbstractEntity()
export class BaseEntity {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    title: string;

}
        

import {Entity, Column} from "typeorm";
import {Person} from "./Person";

@Entity()
export class Employee extends Person {

    @Column()
    salary: number;

}
        

import {Entity, Column} from "typeorm";
import {Person} from "./Person";

@Entity()
export class Student extends Person {

    @Column()
    faculty: string;

}
        

import {Entity, Column} from "typeorm";
import {Person} from "./Person";

@Entity()
export class Homesitter extends Person {

    @Column()
    numberOfKids: number;

}
        

Single table inheritance

Single table inheritance is when you have multiple entities and they all are mapped into a single table. Example:


import {Entity, Column, PrimaryGeneratedColumn, TableInheritance, DiscriminatorColumn} from "typeorm";

@Entity()
@EntityInheritance("single-table")
@DiscriminatorColumn({ name: "type", type: "string"})
export class Person {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

}
        

import {SingleEntityChild, Column} from "typeorm";
import {Person} from "./Person";

@SingleEntityChild()
export class Employee extends Person {

    @Column()
    salary: number;

}
        

import {SingleEntityChild, Column} from "typeorm";
import {Person} from "./Person";

@SingleEntityChild()
export class Student extends Person {

    @Column()
    faculty: string;

}
        

import {SingleEntityChild, Column} from "typeorm";
import {Person} from "./Person";

@SingleEntityChild()
export class Homesitter extends Person {

    @Column()
    numberOfKids: number;

}
        

Class table inheritance

Class table inheritance uses separate table for each class in your inheritance hierarchy. Example:


import {Entity, Column, PrimaryGeneratedColumn, TableInheritance, DiscriminatorColumn} from "typeorm";

@Entity()
@EntityInheritance("class-table")
@DiscriminatorColumn({ name: "type", type: "string"})
export class Person {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

}
        

import {ClassEntityChild, Column} from "typeorm";
import {Person} from "./Person";

@ClassEntityChild()
export class Employee extends Person {

    @Column()
    salary: number;

}
        

import {ClassEntityChild, Column} from "typeorm";
import {Person} from "./Person";

@ClassEntityChild()
export class Student extends Person {

    @Column()
    faculty: string;

}
        

import {ClassEntityChild, Column} from "typeorm";
import {Person} from "./Person";

@ClassEntityChild()
export class Homesitter extends Person {

    @Column()
    numberOfKids: number;

}
        
Fork me on GitHub