Separating Entity Definition

Defining Schemas

You can define an entity and its columns right in the model, using decorators.But some people prefer to define an entity and its columns inside separate fileswhich are called “entity schemas” in TypeORM.

Simple definition example:

  1. import {EntitySchema} from "typeorm";
  2. export const CategoryEntity = new EntitySchema({
  3. name: "category",
  4. columns: {
  5. id: {
  6. type: Number,
  7. primary: true,
  8. generated: true
  9. },
  10. name: {
  11. type: String
  12. }
  13. }
  14. });

Example with relations:

  1. import {EntitySchema} from "typeorm";
  2. export const PostEntity = new EntitySchema({
  3. name: "post",
  4. columns: {
  5. id: {
  6. type: Number,
  7. primary: true,
  8. generated: true
  9. },
  10. title: {
  11. type: String
  12. },
  13. text: {
  14. type: String
  15. }
  16. },
  17. relations: {
  18. categories: {
  19. type: "many-to-many",
  20. target: "category" // CategoryEntity
  21. }
  22. }
  23. });

Complex example:

  1. import {EntitySchema} from "typeorm";
  2. export const PersonSchema = new EntitySchema({
  3. name: "person",
  4. columns: {
  5. id: {
  6. primary: true,
  7. type: "int",
  8. generated: "increment"
  9. },
  10. firstName: {
  11. type: String,
  12. length: 30
  13. },
  14. lastName: {
  15. type: String,
  16. length: 50,
  17. nullable: false
  18. },
  19. age: {
  20. type: Number,
  21. nullable: false
  22. }
  23. },
  24. checks: [
  25. { expression: `"firstName" <> 'John' AND "lastName" <> 'Doe'` },
  26. { expression: `"age" > 18` }
  27. ],
  28. indices: [
  29. {
  30. name: "IDX_TEST",
  31. unique: true,
  32. columns: [
  33. "firstName",
  34. "lastName"
  35. ]
  36. }
  37. ],
  38. uniques: [
  39. {
  40. name: "UNIQUE_TEST",
  41. columns: [
  42. "firstName",
  43. "lastName"
  44. ]
  45. }
  46. ]
  47. });

If you want to make your entity typesafe, you can define a model and specify it in schema definition:

  1. import {EntitySchema} from "typeorm";
  2. export interface Category {
  3. id: number;
  4. name: string;
  5. }
  6. export const CategoryEntity = new EntitySchema<Category>({
  7. name: "category",
  8. columns: {
  9. id: {
  10. type: Number,
  11. primary: true,
  12. generated: true
  13. },
  14. name: {
  15. type: String
  16. }
  17. }
  18. });

Extending Schemas

When using the Decorator approach it is easy to extend basic columns to an abstract class and simply extend this.For example, your id, createdAt and updatedAt columns may be defined in such a BaseEntity. For more details, seethe documentation on concrete table inheritance.

When using the EntitySchema approach, this is not possible. However, you can use the Spread Operator (...) to youradvantage.

Reconsider the Category example from above. You may want to extract basic column descriptions and reuse it acrossyour other schemas. This may be done in the following way:

  1. import {EntitySchemaColumnOptions} from "typeorm";
  2. export const BaseColumnSchemaPart = {
  3. id: {
  4. type: Number,
  5. primary: true,
  6. generated: true,
  7. } as EntitySchemaColumnOptions,
  8. createdAt: {
  9. name: 'created_at',
  10. type: 'timestamp with time zone',
  11. createDate: true,
  12. } as EntitySchemaColumnOptions,
  13. updatedAt: {
  14. name: 'updated_at',
  15. type: 'timestamp with time zone',
  16. updateDate: true,
  17. } as EntitySchemaColumnOptions,
  18. };

Now you can use the BaseColumnSchemaPart in your other schema models, like this:

  1. export const CategoryEntity = new EntitySchema<Category>({
  2. name: "category",
  3. columns: {
  4. ...BaseColumnSchemaPart,
  5. // the CategoryEntity now has the defined id, createdAt, updatedAt columns!
  6. // in addition, the following NEW fields are defined
  7. name: {
  8. type: String
  9. }
  10. }
  11. });

Be sure to add the extended columns also to the Category interface (e.g., via export interface Category extend BaseEntity).

Using Schemas to Query / Insert Data

Of course, you can use the defined schemas in your repositories or entity manager as you would use the decorators.Consider the previously defined Category example (with its Interface and CategoryEntity schema in order to getsome data or manipulate the database.

  1. // request data
  2. const categoryRepository = getRepository<Category>(CategoryEntity);
  3. const category = await categoryRepository.findOne(1); // category is properly typed!
  4. // insert a new category into the database
  5. const categoryDTO = {
  6. // note that the ID is autogenerated; see the schema above
  7. name: 'new category',
  8. };
  9. const newCategory = await categoryRepository.save(categoryDTO);