loading...

Sequelize + Typescript ตอนที่ 1

pthongtaem profile image Polchompunoot Thongtaem Na Ayudhya Updated on ・2 min read

พวกเราใช้ JavaScript กันอย่างมีความสุขตลอดมา อยู่ๆ ก็มีน้องคนนึงถามขึ้นมาว่า "พี่ๆ เราไม่ใช้ TypeScript เหรอ" จากนั้นก็แลกเปลี่ยนความคิดกันไปมา สรุปได้ว่าเราจะเปลี่ยนไปใช้ TypeScript กัน อะไรคือเหตุผลค่อยว่ากันเนอะ สรุปว่าตอนนี้จะใช้ก็แล้วกัน

เท่าที่กลับไปดูอย่างอื่นก็มีวิธีที่จะทำเป็น TypeScript เกือบหมดแล้ว จะมีก็แต่ ORM ที่เราเลือกใช้ Sequelize (v. 5) ที่ยังดูเหมือนไม่ค่อยชัดเจนกับเรื่องนี้เท่าไหร่ ถึงขั้นเราจะเลิกใช้ Sequelize หนีไป TypeORM กันเลยที่เดียว แต่พอไปลองจริงๆ TypeORM ยังมีหลายอย่างที่เราคิดว่ายังไม่สมบูรณ์เหมือนกับ Sequelize สุดท้ายก็กลับมาตายรังที่ Sequelize และก็ยังตัดสินใจไม่ใช้ sequelize-typescript อีกด้วย เอาจริงๆ วิธีการก็ไม่ต่างจากเดิมเท่าไหร่แค่เปลี่ยนอะไรนิดๆ หน่อยๆ และนี่คือวิธีการใช้ Sequelize กับ TypeScript ที่ทีมเราใช้กันอยู่ตอนนี้

เครื่องมือเครื่องใช้

ก่อนหน้านี้ใช้ babel มาตลอด หลังจากเปลี่ยนมาใช้ TypeScript ก็เปลี่ยนมาใช้ ts-node เป็นตัวช่วย ก็รู้ว่าง่ายกว่า babel มาก สามารถใช้ร่วมกับ JavaScript ปกติได้เลย ใครที่ config อะไรแปลกๆ ใน babel ก็ลอง test กันดูก่อนนะ ส่วน dependencies ที่ต้องใช้เพิ่มเติมจาก Sequelize ก็คือ

  • @types/node
  • @types/validator
  • @types/bluebird

สร้าง Connection

ในบทความนี้ขอใช้ database เป็น sqlite เผื่อใครจะ clone code ไปทำตามจะได้ลุยกันได้เลย ตามจริงจะใช้ตัวไหนก็ไม่ต่างกันเพราะเราใช้ ORM แล้วนิเนอะ แล้วก็สร้าง connection เหมือนที่เราเคยสร้างตามปกติ

import { Sequelize } from 'sequelize';

export const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: './src/database/demo.db',
});

สร้าง Model หรือ Table นั่นแหละ

ใครที่เคยสร้าง Model แบบ sequelize.define ก็เปลี่ยนมาใช้ class extends Model มันง่ายกว่าเยอะมาก สร้าง class กำหนด type แล้วใช้ Sequelize init เพื่อสร้าง Sequelize Model เท่านี้ Model ก็พร้อมใช้งานแล้ว ขอสร้างไว้ 3 Model ไว้ทำ association ในตอนต่อไปละกันเนอะ

import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../database/connection';

export class Actor extends Model {
  id!: number;

  firstName!: string;

  lastName!: string;

  createdAt!: Date;

  UpdatedAt!: Date;
}

Actor.init(
  {
    firstName: {
      type: DataTypes.STRING,
      allowNull: false,
    },

    lastName: {
      type: DataTypes.STRING,
      allowNull: false,
    },
  },
  {
    sequelize,
    tableName: 'actor',
    freezeTableName: true,
  },
);
import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../database/connection';

export class Movie extends Model {
  id!: number;

  title!: string;

  year!: number;

  createdAt!: Date;

  UpdatedAt!: Date;
}

Movie.init(
  {
    title: {
      type: DataTypes.STRING,
      allowNull: false,
    },

    year: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
  },
  {
    sequelize,
    tableName: 'movie',
    freezeTableName: true,
  },
);
import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../database/connection';

export class Genre extends Model {
  id!: number;

  name!: string;

  createdAt!: Date;

  UpdatedAt!: Date;
}

Genre.init(
  {
    name: {
      type: DataTypes.STRING,
      allowNull: false,
    },
  },
  {
    sequelize,
    tableName: 'genre',
    freezeTableName: true,
  },
);

ทดสอบ Connection

เมื่อได้ Connection กับ Model แล้วก็มาลองทดสอบกันหน่อย ปกติเราสามารถเรียก class ที่เราสร้างเพื่อทดสอบ Connection ได้เลย แต่ถ้ามีหลายๆ Model เราควรให้ทุก Model init ให้เรียบร้อยก่อน จึงสร้าง file รวมขึ้นมาเพื่อ init ทุก Model ซึ่งวิธีนี้จะช่วยแก้ปัญหาการทำ associations ซึ่งจะกล่าวถึงในตอนต่อไป

import './Actor';
import './Movie';
import './Genre'

จากนั้นก็สามารถเรียก sequelize.authenticate() เพื่อทดสอบ Connection ได้ตามปกติและสามารถทดสอบการ Query จาก Model ได้เลย จะเห็นว่าแต่ละ Model จะมี type ติดมาด้วยแล้ว

import './models';
import { sequelize } from './database/connection';
import { Actor } from './models/Actor';

(async () => {
  try {
    await sequelize.authenticate();
    console.log('Connection has been established successfully.');

    // Find all actors
    const actors = await Actor.findAll();

    console.log(actors);
  } catch (err) {
    console.error('Unable to connect to the database:', err);
  }
})();

สรุป

หลังจากทำตามขึ้นตอนด้านบนเราก็จะมี Model พร้อมใช้งาน โดยสามารถใช้งานได้ตามปกติไม่ต่างจากที่ทำใน JavaScript เลย เพียงแต่จะมี type ติดไปด้วย แต่ยังมีอีกส่วนนึงที่ต่างไปจากตอนใช้ JavaScript ก็คือการทำ association พวก One-to-Many, Many-to-Many นั่นแหละ ไว้เจอกันใหม่ตอนหน้าครับ

GitHub logo pthongtaem / sequelize-typescript-demo

sequelize typescript demo

Discussion

pic
Editor guide