TypeScript เป็นภาษาคอมพิวเตอร์ที่เป็น open-source อีกภาษาหนึ่ง ที่พัฒนาโดยบริษัทไมโครซอฟต์ เป็นภาษาที่เป็นแบบ High-Level และแตกต่างจากภาษาอื่นๆ ที่จะ Compile เป็น Machine Code แต่ TypeScript compile เป็นภาษา JavaScript
เนื่องจาก JavaScript เป็นภาษาที่เป็น Interpreted Language ที่ไม่ต้องทำการ Compile ก่อน Run เช่นเดียวกันกับ Python , PHP อื่นๆ ดังนั้น ต้องรันก่อนถึงจะรู้ว่ามี Error
TypeScript จะเป็น Type System เพิ่มเติมของ JavaScript และเป็นการเอา Features ในอนาคตของ JavaScript มาพัฒนาก่อน
- เป็น Compile Time Error เราจะสามารถเห็น Error ได้ตั้งแต่ตอนเขียนว่าระบบเราจะบัคตรงไหนบ้าง
- รองรับการเขียนแบบ Strong type หรือ Static type หรือพูดง่ายๆ ว่ามีต้องประกาศ type ของตัวแปร
- ทำงานได้กับทุกๆ Browser และ JS Engine
- ใช้เวลาเขียนนานหน่อยแต่ง่ายต่อการ debug และการหา Error มาก
- เหมาะกับการใช้ JavaScript ในการทำระบบที่มีขนาดใหญ่ อย่างเช่น NodeJS เพราะสาเหตุของการเป็น Type safe
- JavaScript เป็น Runtime Error เพราะงั้นเราจะไม่เจอบัคจนกว่าจะรันไฟล์
JavaScript and TypeScript
| JavaScript | TypeScript | |
|---|---|---|
| Type System | Dynamically typed | Statically typed |
| Compilation | Interpreted | Compiled |
| Type Annotations | Not required | Required |
| Tooling | Limited type checking support | Rich type checking support |
| Code Quality | More prone to errors and bugs due to dynamic typing | Less prone to errors and bugs due to static typing |
| Development Speed | Fast due to flexibility of dynamic typing | Slower due to required type annotations and compilation step |
| Maintainability | May be harder to maintain and refactor as codebase grows | Easier to maintain and refactor due to better type checking and tooling support |
Setup
Tutorial เริ่ม project ด้วย:
tsc --int
รันด้วย watch mode เพื่ออ่านไฟล์ tsconfig.json ด้วย
tsc -w
Declaration
การกำหนดค่าตัวแปรขณะที่ประกาศตัวแปร อย่าง var กับ let ไม่จำเป็นที่จะต้องกำหนดค่าตัวแปรตอนประกาศก็ได้ แต่ว่า const นั้นจำเป็นที่จะต้องกำหนดต่าตัวแปรให้มัน
| Declaration Type | Scope | Declaration | Update value | Re-declare |
|---|---|---|---|---|
| var | global, function | Without initialize | Yes | Yes |
| const | block | Need initialize | No | No |
| let | block | Without initialize | Yes | No |
แนะนำให้ประกาศตัวแปรด้วย
constเสมอและค่อยเปลี่ยนเป็นletถ้าคุณต้องการ เปลี่ยนแปลงค่า (mutate) หรือ assign ค่าให้ตัวแปรในภายหลัง
Scope
กำหนดระดับการเข้าถึงของตัวแปรนั้นๆ
- Global Scope: ประกาศแบบ global ข้างนอก function/class ใดๆ
- Function Scope: ประกาศและเข้าถึงได้ใน function/class
- Block Scope: ประกาศและเข้าถึงได้ใน code block (ส่วนที่ปิดด้วย
()เช่น if/try/catch/while)
Basic Types
// Number
const n1: number = 1
const n2: number = 1.1
// Boolean
const n3: boolean = true
// Array
const n5: string[] = ['1','2','3']
// String
const n8: string = 'It\'s a string'Any
การใช้ข้อมูลชนิด any เป็นสิ่งที่ควรหลีกเลี่ยง เพราะมันไม่ถูก type-check และสามารถรับข้อมูลชนิดไหนมาก็ได้
let hero
function getHero() {
return "Batman"
}
hero = getHero() // anyควรประกาศ type เพื่อระบุชนิดอย่างชัดเจน
let hero: string
function getHero() {
return "Batman"
}
hero = getHero() // stringObject
Objects are variables too. But objects can contain many values.
const car: { type: string, model: string, year: number } = {
type: "Toyota",
model: "Corolla",
year: 2009
}
// The parameter's type annotation is an object type
function printCoord(pt: { x: number; y: number }) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 3, y: 7 });Type Alias
- Type Aliases allow defining types with a custom name (an Alias).
- Type Aliases can be used for primitives like
stringor more complex types such asobjectsandarrays:
type Point = {
x: number;
y: number;
};
// Exactly the same as the earlier example
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 100, y: 100 });Readonly and Optional:
type User = {
readonly _id: string // readonly
name: string
age: number
isActive: true // literal type
creditcard?: number // optional
}Reuse types:
type cardNumber = {
cardNumber: string
}
type cardHolder = {
cardHolder: string
}
type cardDetail = cardNumber &
cardHolder & {
cvv: number
}Interface
เป็นวิธีการกำหนดประเภทข้อมูลให้กับออบเจ็คแบบนามธรรมเพื่อที่จะระบุ Property ที่ออบเจ็คสามารถมีและประเภทข้อมูลที่ Property จะมีได้
interface User {
dbId: number
name: string
age: number
}
const user01: User = {
dbId: 1,
name: "John",
age: 20,
}Interface สามารถสืยทอดได้โดยใช้ extends
interface User {
dbId: number
name: string
age: number
}
interface UserWithAddress extends User {
address: string
}Type vs Interface
Read More
สำหรับการกำหนดรูปร่างหน้าตาของออปเจกต์นั้น สามารถใช้ได้ทั้ง type และ interface
interface Point {
x: number
y: number
}
type Point = {
x: number
y: number
}สังเกตว่าการใช้ interface จะคล้ายกับการสร้าง Class และการใช้ type จะคล้ายการประกาศค่าของตัวแปรโดยใช้ = เพราะฉะนั้นหากเป็นกรณีที่ตั้งชื่อให้กับ Type มาตรฐานทั่วไป หรือทำ Literal Types จะไม่สามารถใช้ interface ได้
type Color = "Yellow" | "Red" // OK
interface Color "Yellow" | "Red" // ❌ ไม่ได้ เพราะไม่ใช่ออบเจกต์ถ้าใช้
interfaceได้ (เช่นกำหนดสำหรับ Object, Class) ก็ใช้ ถ้าทำไม่ได้ค่อยใช้typeแทน
Union
หลายครั้งที่ Type ที่สร้างขึ้นมาจะไม่ครอบคลุมการใช้งานได้ทั้งหมด หรือมีความต้องการที่จะใช้ตัวแปรเก็บค่าที่มีความซับซ้อนมากขึ้น เราสามารถใช้ Union Types และ Intersection Types มาช่วยได้
type ID = string | number
const a: ID = "abc"
const b: ID = 101อีกตัวอย่างหนึ่งที่จะได้ใช้ Union Type เช่น Literal Types
type Color = "red" | "green" | "blue"
function printColorCode(c: Color): string {
switch (c) {
case "red":
return "#FF0000"
case "green":
return "#00FF00"
case "blue":
return "#0000FF"
}ประกาศ Union Type ให้กับ array ให้ใส่ได้ทั้ง number และ string
const data1: number[] = [1, 2, 3]
const data2: string[] = ["1", "2", "3"]
const data3: (number | string)[] = [1, "2", 3]
const data4: number[] | string[] = [1, 2, 3] // or ["1", "2", "3"]Intersection
จะใช้กับ Interface จะเป็นเสมือนการ “ต่อ” Interface ต่างๆ เข้าด้วยกัน
interface Colorful {
color: string
}
interface Circle {
radius: number
}
interface Square {
size: number
}
interface Measurable {
area: () => number
}
// มี color, radius และฟังก์ชั่น area
type ColorfulCircle = Colorful & Circle & Measurable
// มี color, size และฟังก์ชั่น area
type ColorfulSquare = Colorful & Square & MeasurableArray
An array is a special variable, which can hold more than one value:
// Type 1
const superHero: string[] = []
superHero.push("Batman")
// Type 2
const heroPower: Array<number> = []
heroPower.push(9000)
// Array of User type
type User = {
name: string
age: number
}
const user: User[] = []
Tuple
หมายถึงข้อมูลที่มีโครงสร้างแบบ array แต่ระบุจำนวนข้อมูลที่แน่นอนพร้อมกำหนดชนิดข้อมูลของแต่ละช่องไว้อย่างเรียบร้อย
const somchai: [name: string, age: number] = ["Somchai", 24]
const rgb: [number, number, number] = [255, 255, 255]Enum
enum ใช้ในการประกาศค่าคงที่ และรวมค่าคงที่ ที่เราต้องการไว้ในกลุ่มเดียวกัน โดยไม่จำเป็นต้องประกาศแยก const แต่ละตัวออกมาเช่น
enum Role {
ADMIN,
READ_ONLY,
AUTHOR,
}
const person = {
name: "Maximilian",
role: Role.ADMIN,
}Function
Function with default paremeter
function signUpUser(name: string, isPaid: boolean = false) {
// ...
}Function return 1 value
function sumNumbers(a: number, b: number): number {
return a + b;
}Arrow Function
Arrow function คือการสร้างฟังก์ชันรูปแบบใหม่ที่สั้นกระชับกว่าเดิม
let loginUsers = (email: string, password: string) => {
// ...
}Example
const getHello = (s: string): string => {
return `Hello ${s}`
}
const heros = ["Thor", "Ironman", "Hulk"]
heros.map((heros: string): string => {
return getHello(heros)
})Class
คือแม่แบบที่ใช้สำหรับสร้างออบเจ็ค ประกอบไปด้วยการกำหนด attribute และ method ที่ออบเจ็คจะมี ใช้แนวคิดของการนำโค้ดกลับมาใช้ซ้ำ (Code-reuse) สามารถสืบทอดคลาส (Inheritance)
Interface เหมือนบอกลักษณะของแม่พิมพ์ Class เหมือนแม่พิมพ์ในการสร้างวัตถุที่ออกแบบโดย interface Object หรือ instance คือผลลัพธ์ที่ถูกสร้างขึ้นโดยแม่พิมพ์
class Rectangle {
width: number;
height: number;
area(): number {
return this.width * this.height;
}
}
let rect: Rectangle = new Rectangle();
rect.width = 3;
rect.height = 4;
console.log(`Area of rect: ${rect.area()}`);Private/ Public/ Protected
ใช้กำหนดระดับการเขาถึงของ attribute
class User {
public name: string // public is default
email: string
private city: string = ""
constructor(name: string, email: string) {
this.name = name
this.email = email
}
}
const user = new User("John", "[email protected]")Alternative
class User {
constructor(
public name: string, // public is default
public email: string,
private city: string = ""
) {}
}Getter/ Setter
class User {
constructor(
public name: string, // public is default
public email: string,
private city: string = ""
) {}
get getInfo(): string {
return `Name: ${this.name} | Email: ${this.email} | City: ${this.city}`
}
set setCity(city: string) {
this.city = city
}
}Inheritance
class SubUser extends User {
isFamily: boolean = true
}Implement
interface TakePhoto {
camaraMode: string
filters: string
burst: number
}
class Instagram implements TakePhoto {
constructor(
public camaraMode: string,
public filters: string,
public burst: number,
public short: boolean // Add new property
) {}
}Generic
เป็นการยืดหยุ่นในการรับค่า parameter
function identity<T>(val: T): T { // T is a type variable
return val
}
identity<string>("hello")
identity(10)
identity(true)
// Using Generics with Interfaces
interface bottle {
name: string
price: number
}
identity<bottle>({ name: "water", price: 10 })Generics in Array
// Regular function
function getSearchProducts<T>(products: T[]): T {
const myIndex = 3
return products[myIndex]
}
// Arow function with generics
const getSearchProducts2 = <T>(products: T[]): T => {
const myIndex = 3
return products[myIndex]
}Generics with Class
interface Quiz {
name: string
type: string
}
interface Course {
name: string
author: string
subject: string
}
class sellableItem<T> {
public cart: T[] = []
addToCart(product: T) {
this.cart.push(product)
}
}Type Narrowing
function detectType(val: number | string) {
if (typeof val === "string") {
return val.toLowerCase()
}
return val + 1
}
function provideId(id: string | null) {
if (!id) {
console.log("Please provide an id")
return
}
id.toLowerCase()
}Reference: