สอนวิธีเซ็ตโปรเจค TypeScript / มาใส่ไทป์ให้ JavaScript เพื่อลดความผิดพลาดในการเขียนโค้ดกันดีกว่า

developer

บทความชุด: JavaScript/Fundamental for beginner

รวมเนื้อหาการใช้ภาษา JavaScript สำหรับมือใหม่ ตั้งแต่หลักการ แนวคิด การทำงานกับเว็บทั้งฝั่งclient-server library&frameworkที่น่าสนใจ จนถึงมาตราฐานการเขียนแบบใหม่ ES6 (ECMAScript6)

 

ภาษา JavaScript นั้นเป็นภาษาที่เริ่มเขียนได้ไม่ยาก ยิ่งถ้าใครเขียนภาษาสาย Structure/OOP เช่น C/C++, C#, Java มาก่อน อาจจะชอบในความเป็น Dynamic Type เราสร้างตัวแปรแล้วเก็บค่าอะไรก็ได้ ทำให้มีความคล่องตัวในการเขียนมากๆ ก่อนที่พอเขียนไปเรื่อยๆ เราจะพบความแปลกของมัน ยิ่งเขียนไปนานๆ เราก็พบว่ามันเป็นภาษาที่ทำให้เกิดบั๊กได้ง่ายมาก และเป็นหนึ่งในภาษาที่น่าปวดหัวที่สุดที่คนโหวตๆ กันเลย ด้วยเหตุผลแรกคือการที่ตัวแปรไม่มี Type นั่นเอง (อีกเหตุผลหนึ่งคือส่วนใหญ่ของคนที่เปลี่ยนมาเขียน JavaScript เคยชินกับภาษาแนว OOP มาก่อน พอมาเขียนภาษาแนว Functional เลยงงหน่อยๆ)

หลักการคือคอมไพล์ออกมาเป็น JavaScript

เอาจริงๆ ตัวภาษา TypeScript เอาไปรันอะไรไม่ได้เลย

แต่เราใช้วิธีการคอมไพล์ไฟล์ .ts ให้ออกมาเป็นไฟล์ .js อีกที หน้าที่ของมันมีแค่นั้นเอง

หรือบางกรณีถ้าเราเขียน React เราอาจจะรู้จักกับ .jsx สำหรับ TypeScript ก็มีไฟล์นามสกุล .tsx ให้ใช้เช่นกัน

Installation มาติดตั้ง TypeScript กัน

สำหรับ TypeScript Compiler นั้นสามารถติดตั้งได้ทั้งผ่าน npm หรือ yarn ด้วยคำสั่งประมาณนี้

npm install -g typescript

พอติดตั้งแล้วเราสามารถใช้คำสั่ง tsc สำหรับคอมไพล์ไฟล์ TypeScript ได้เลย

วิธีนี้เป็นการติดตั้งแบบ global คือติดตั้งครั้งเดียว ใช้ได้ทุกที่เลย แต่ถ้าอยากติดตั้งแต่ในโปรเจคๆ ไปก็สามารถทำได้ด้วย

npm install typescript --save-dev

หรือจะใช้งานผ่าน npx ก็ได้เช่นกัน

npx tsc

flag --save-dev หรือตัวย่อ -D ใส้ไว้เพื่อระบุว่าเราใช้แพ็กเกจนี้เฉพาะตอน develop เท่านั้น เมื่อไหร่ที่จะ build โปรเจคเอาไปใช้จริง ไม่ต้องเอาติดไปด้วยนะ เพราะอย่างที่บอกคือ TypeScript นั้นตัวมันไม่ได้เอาไปรัน แต่คอมไพล์เป็น JavaScript เมื่อไหร่ที่เขียนเสร็จแล้ว ก็ไม่ต้องใช้ต่อแล้ว

คอมไพล์ไฟล์ TypeScript

เริ่มแรกลองมาสร้างไฟล์ TypeScript กันดีกว่า

//app.ts

function sum(n: number): number {
    let sum: number = 0
    for(let i = 0; i < n; i++){
        sum += i
    }
    return sum
}

const total: number = sum(100)

console.log(total)

เขียนโค้ดนี้แล้วเซฟเป็นไฟล์ชื่อ app.ts ไว้ จะเห็นว่า syntax ทั้งหมดนั้นเหมือนกัน JavaScript ทุกอย่าง ที่เพิ่มเติมมาก็แค่หลังชื่อตัวแปร ตอนที่ประกาศตัวแปรและ parameter เราจะต้องกำหนดชนิดตัวแปรลงไปด้วย โดยใช้ตัว : ตามแพทเทิร์นนี้

variable-name: type

ไทป์ที่ใช้ได้ก็เช่น

let decimal: number = 6
let hex: number = 0xf00d
let binary: number = 0b1010
let octal: number = 0o744

let color: string = "blue"

let isDone: boolean = false

สำหรับตัวแปรประเภท Array นั้นประกาศได้ 2 แบบคือ

let list: number[] = [1, 2, 3]
let list: Array<number> = [1, 2, 3]

ส่วนตัวแปรแบบ Object นั้นจะต้องสร้าง interface เพื่อกำหนดไทป์ขึ้นมาก่อน

interface Point {
    x: number
    y: number
}

let myPoint: Point = { x: 10, y: 20 }

สำหรับ TypeScript นั้น เราไม่สามารถสร้างตัวแปรแบบไม่กำหนดไทป์ได้ แต่ถ้าเราไม่รู้ไทป์จริงๆ เราสามารถประกาศไทป์ any ได้ (แต่ก็ไม่แนะนำให้ทำนะ)


จากนั้นเราใช้คำสั่ง tsc ในการคอมไพล์ไฟล์ TypeScript ของเรา

tsc app.ts

หลังจากคอมไพล์เสร็จแล้ว เราจะได้อีกไฟล์เพิ่มมาในชื่อเดียวกันแต่เป็นนามสกุล .js แทน

เมื่อเราเอามาเปิดดูก็จะพบว่ามันมีหน้าตาคล้ายๆ กับโค้ด TypeScript ที่เราเขียนไป แต่ชนิดตัวแปรที่เคยประกาศจะหายไป และอาจจะมีอะไรอีกนิดหน่อยด้วย (เช่นมี ; เพิ่มเข้ามาให้ จากที่เคยใช้ let, const ก็เปลี่ยนเป็น var) ซึ่งโดยร่วมไม่ได้ทำให้โลจิคเปลี่ยนไปนะ

// app.js

function sum(n) {
    var sum = 0;
    for (var i = 0; i < n; i++) {
        sum += i;
    }
    return sum;
}
var total = sum(100);
console.log(total);

ซึ่งจุดนี้อาจจะทำให้คนที่เพิ่งเริ่มใช้ TypeScript สงสัยว่าถ้ามันแค่ตัด Type ทิ้งไป แล้วทำไมเราไม่เขียน JavaScript ตรงๆ ไปเลยล่ะ?

เช่นผลคือ TypeScript สามารถช่วยเราในส่วนของการเช็ก Compiler-Time Error ได้

เช่นโค้ดนี้

เราประกาศฟังก์ชันที่ต้องรับ number แต่เวลาเรียกใช้งาน ดันใส่ string เข้าไป ถ้าเป็น JavaScript จะสามารถนำไปรันได้ (แต่ผลออกมาจะเกิด Runtime-Error หรือมีโลจิคผิดพลาดตรงไหนจะไม่สามารถรู้ได้เลย)

แต่สำหรับ TypeScript นั้นจะแจ้งออกมาตั้งแต่ตอนสั่งคอมไพล์เลยว่าเรามีการเขียนผิดพลาดเกิดขึ้นนะ และ Editor ส่วนใหญ่ก็สามารถแสดงผลข้อผิดพลาดพวกนี้แบบ real time ได้อยู่แล้วด้วย ทำให้ไม่ต้องเสียเวลาพิมพ์ไปซะนาน แต่พอเอามารันเพิ่งจะรู้ว่าพิมพ์ผิดไป

เริ่มสร้างโปรเจคกันเถอะ

ในโปรเจคขนาดใหญ่ แน่นอนว่าเราไม่ได้มีแค่ไฟล์ sourcecode แค่ไฟล์สองไฟล์ แต่อาจจะมีเป็นร้อยๆ ไฟล์ การจะมานั่งคอมไพล์ TypeScript ทีละไฟล์นั้นทำไม่ได้แน่นอน (จริงๆ ก็ทำได้ แต่ใครจะทำนะ !)

การสร้างโปรเจคเลยเป็นทางเลือกที่ดีกว่า เช่นเราอาจจะสร้างโฟลเดอร์ /src สำหรับเอาไว้เก็บไฟล์ .ts ทั้งหมด และสร้างโฟลเดอร์ /dist หรือ distribute เอาไว้เก็บไฟล์ JavaScript

.
├── src
│   ├── app1.ts
│   ├── app2.ts
│   ├── app3.ts
│   └── ...
└── dist
    ├── app1.js
    ├── app2.js
    ├── app3.js
    └── ...

ซึ่งสำหรับ TypeScript เราสามารถใช้คำสั่งนี้

tsc --init

เพื่อกำหนดว่าโฟลเดอร์นั้นจะเป็นโปรเจค TypeScript ได้ หลังจากสั่งคำสั่งนั้นแล้ว เราจะได้ไฟล์ tsconfig.json มา ภายในไฟล์จะมี config สำหรับโปรเจคอยู่ หน้าตาประมาณนี้

รายละเอียดการเซ็ตค่า tsconfig สามารถดูได้ที่เว็บไซต์ของ TypeScript

ปกติการตั้งค่าหลักๆ ก็จะใช้ของที่ TypeScript สร้างมาให้ ยกเว้นบางตัวที่เราต้องเซ็ตเอง เช่น

{
  "compilerOptions": {

    // สั่งให้คอมไพล์ออกมาเป็น JavaScript ES6
    "target": "es6",

    // ชื่อโหลเดอร์ที่ output ไฟล์ JavaScript ที่คอมไพล์แล้ว
    "outDir": "./dist",

    // ชื่อโฟลเดอร์ sourcecode ไฟล์ TypeScript
    "rootDir": "./src",

    // หากใช้งานกับ React คือมีไฟล์ .tsx ให้คอมไพล์เป็น .jsx ด้วย
    "jsx": "react",

    // หากใช้กับ node
    "moduleResolution": "node",
  },

  // กำหนดขอบเขตของไฟล์ที่จะให้คอมไพล์
  // เช่น ทุกไฟล์ที่นามสกุล .ts ในโฟลเดอร์ไหนก็ได้ใต้ /src
  "include": [
      "src/**/*.ts"
  ],

  // กำหนดไฟล์และโฟลเดอร์ที่ไม่ต้องคอมไพล์ 
  // เช่นโฟลเดอร์ node_modules หรือไฟล์ spec
  "exclude": [
      "node_modules",
      "**/*.spec.ts"
  ]
}

จากนั้นเวลาเราจะคอมไพล์ ก็สั่งแค่

tsc

มันก็จะเป็นการคอมไพล์ทุกไฟล์ในทั้งโฟลเดอร์ /src/ ที่เรากำหนดไว้

แต่นี่ก็เป็นการคอมไพล์แค่ครั้งเดียว ถ้าเรามีการแก้ไขไฟล์ TypeScript เพิ่ม เราก็ต้องสั่งคอมไพล์อีกรอบ ถ้าไม่อยากจะมาสั่งคอมไพล์ทุกรอบที่แก้ไขโค้ด เราสามารถสั่งคอมไพล์แบบ watch ได้

tsc --watch

คำสั่งนี้จะเป็นการสั่งให้คอมไพล์พร้อมกับ watch หรือคอยดูไฟล์ทุกไฟล์เอาไว้ด้วย ถ้ามีการเปลี่ยนแปลงให้คอมไพล์ใหม่ทันทีโดยเราไม่ต้องสั่งอีกรอบ

12 Total Views 3 Views Today
Ta

Ta

สิ่งมีชีวิตตัวอ้วนๆ กลมๆ เคลื่อนที่ไปไหนโดยการกลิ้ง .. ถนัดการดำรงชีวิตโดยไม่โดนแสงแดด
ปัจจุบันเป็น Senior Software Engineer อยู่ที่ Centrillion Technology
งานอดิเรกคือ เขียนโปรแกรม อ่านหนังสือ เขียนบทความ วาดรูป และ เล่นแบดมินตัน

You may also like...