TypeScript e Sequelize: Como Trabalhar com ORM Tipado

18/09/2024

O Que é o Sequelize e Por Que Usá-lo com TypeScript?

Sequelize é um ORM (Object-Relational Mapping) popular para Node.js que facilita a interação com bancos de dados relacionais como MySQL, PostgreSQL, SQLite e outros. Ao usá-lo com TypeScript, você pode aproveitar a tipagem estática para garantir que consultas, transações e manipulações de dados estejam corretas, proporcionando uma maior segurança e previsibilidade no código.

O uso de TypeScript com Sequelize permite que você defina modelos de banco de dados de forma clara e tipada, garantindo que as interações com o banco de dados estejam alinhadas com os tipos definidos no código.

Configurando TypeScript com Sequelize

Para começar, precisamos configurar um projeto Node.js com TypeScript e Sequelize. Siga os passos abaixo para instalar e configurar as dependências.

1. Instalando Dependências

No terminal, execute os seguintes comandos para instalar o Sequelize, TypeScript e os drivers necessários para o banco de dados:

npm install sequelize sequelize-typescript mysql2
npm install --save-dev typescript @types/node @types/sequelize

Esses pacotes incluem o sequelize e seu adaptador para MySQL (mysql2). O pacote sequelize-typescript facilita o uso de Sequelize com TypeScript, permitindo que você defina modelos e associações de forma tipada.

2. Configurando o tsconfig.json

Crie o arquivo tsconfig.json na raiz do projeto com a seguinte configuração:

{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true
  },
  "include": ["src/**/*"]
}

Essa configuração garante que o TypeScript compile o código para ES6 e use módulos CommonJS, que são padrão no Node.js.

Criando e Tipando Modelos no Sequelize com TypeScript

Ao usar Sequelize com TypeScript, podemos definir os modelos de banco de dados como classes, utilizando a sintaxe e os decorators do sequelize-typescript. Isso facilita a tipagem de cada campo do modelo e suas associações.

1. Criando um Modelo de Usuário

Vamos criar um modelo tipado para um usuário, que incluirá campos como id, nome, email e dataNascimento.

Em src/models/Usuario.ts, adicione o seguinte código:

import { Table, Column, Model, DataType } from 'sequelize-typescript';

@Table({
  tableName: 'usuarios',
  timestamps: true
})
export class Usuario extends Model<Usuario> {
  @Column({
    type: DataType.INTEGER,
    autoIncrement: true,
    primaryKey: true
  })
  id!: number;

  @Column({
    type: DataType.STRING,
    allowNull: false
  })
  nome!: string;

  @Column({
    type: DataType.STRING,
    allowNull: false,
    unique: true
  })
  email!: string;

  @Column({
    type: DataType.DATE,
    allowNull: true
  })
  dataNascimento?: Date;
}

Neste exemplo, usamos decorators como @Table e @Column para definir a tabela e seus campos. O TypeScript garante que os tipos de cada campo estejam corretos, como string para nome e number para id.

Configurando a Conexão com o Banco de Dados

Agora, vamos configurar a conexão com o banco de dados e associar os modelos ao Sequelize. Em src/database/index.ts, adicione o seguinte código para configurar a conexão:

import { Sequelize } from 'sequelize-typescript';
import { Usuario } from '../models/Usuario';

const sequelize = new Sequelize({
  dialect: 'mysql',
  host: 'localhost',
  username: 'root',
  password: 'senha123',
  database: 'meu_banco_de_dados',
  models: [Usuario],
});

export default sequelize;

Aqui, configuramos o Sequelize para se conectar a um banco de dados MySQL local e associamos o modelo Usuario à instância do Sequelize. Todos os modelos que forem definidos em models devem ser adicionados à propriedade models do Sequelize.

Criando e Consultando Registros com TypeScript e Sequelize

Com o modelo de usuário configurado e a conexão com o banco de dados estabelecida, podemos agora criar e consultar registros usando Sequelize com TypeScript.

1. Criando um Novo Registro

Veja como criar um novo registro no banco de dados com o modelo Usuario:

import { Usuario } from './models/Usuario';
import sequelize from './database';

// Sincronizando o banco de dados e criando um usuário
async function criarUsuario() {
  await sequelize.sync();  // Sincroniza as tabelas no banco de dados

  const novoUsuario = await Usuario.create({
    nome: 'Mauro Souza',
    email: 'mauro@example.com',
    dataNascimento: new Date('1990-01-01')
  });

  console.log(novoUsuario);
}

criarUsuario();

A função create é usada para inserir um novo registro na tabela usuarios. O TypeScript garante que os valores fornecidos estejam no formato correto, conforme definido no modelo Usuario.

2. Consultando Registros

Veja como consultar registros existentes no banco de dados:

async function buscarUsuarios() {
  const usuarios = await Usuario.findAll();
  console.log(usuarios);
}

buscarUsuarios();

A função findAll retorna uma lista de todos os usuários no banco de dados. O TypeScript garante que o retorno seja tipado corretamente como uma lista de objetos do tipo Usuario.

Definindo Relacionamentos Entre Modelos

Sequelize suporta relacionamentos entre tabelas, como hasMany, belongsTo, hasOne e belongsToMany. Com TypeScript, podemos definir esses relacionamentos de forma tipada.

1. Exemplo de Relacionamento hasMany

Vamos criar um modelo de Postagem que estará relacionado com o modelo de Usuario, onde um usuário pode ter várias postagens:

import { Table, Column, Model, DataType, ForeignKey, BelongsTo } from 'sequelize-typescript';
import { Usuario } from './Usuario';

@Table({
  tableName: 'postagens',
  timestamps: true
})
export class Postagem extends Model<Postagem> {
  @Column({
    type: DataType.INTEGER,
    autoIncrement: true,
    primaryKey: true
  })
  id!: number;

  @Column({
    type: DataType.STRING,
    allowNull: false
  })
  titulo!: string;

  @Column({
    type: DataType.TEXT,
    allowNull: false
  })
  conteudo!: string;

  @ForeignKey(() => Usuario)
  @Column({
    type: DataType.INTEGER,
    allowNull: false
  })
  usuarioId!: number;

  @BelongsTo(() => Usuario)
  usuario!: Usuario;
}

Aqui, definimos uma chave estrangeira usuarioId para a relação com o modelo Usuario, e o decorator @BelongsTo cria a associação. O TypeScript garante que os relacionamentos estejam corretamente definidos.

Boas Práticas ao Usar Sequelize com TypeScript

  • Defina Tipos Claros para Modelos: Sempre defina tipos claros para cada campo no modelo para garantir que os dados sejam corretamente manipulados em todas as operações.
  • Use Decorators: O uso de decorators como @Table e @Column com sequelize-typescript facilita a definição e tipagem dos modelos.
  • Sincronização de Modelos: Use o método sync() do Sequelize para garantir que o esquema do banco de dados esteja em sincronia com os modelos definidos no código.
  • Verifique Relacionamentos: Ao definir associações entre tabelas, garanta que os relacionamentos estejam corretamente configurados e tipados.

Conclusão

O uso de Sequelize com TypeScript oferece uma maneira robusta e tipada de trabalhar com bancos de dados relacionais no Node.js. Com a tipagem estática do TypeScript, você pode garantir que os modelos, consultas e operações de banco de dados sejam executados de forma segura e eficiente. Usando as ferramentas adequadas, como sequelize-typescript, você pode melhorar a manutenibilidade e previsibilidade do código em projetos maiores.