โดยปกติผมจะเขียนโค้ดอยู่คนเดียว ความ dynamic type ของ JavaScript ก็ไม่ได้สร้างปัญหา สร้าง bug ให้กับผม แต่เนื่องจาก ต้องการจะลองใช้งาน Nestjs ซึเขียนด้วย TypeScript จึงบันทึกเอาไว้สักหน่อยว่าจะเปลี่ยนจาก JavaScript ไปยัง TypeScript นั้นต้องทำยังไงบ้าง
Prerequisites
- มีความเข้าใจภาษา JavaScript ระดับหนึ่ง
- ตั้งค่าโปรเจคเพิ่มเขียน TypeScript จาก ที่นี่
TypeScript คืออะไร 🤔
ซึ่งถ้าถามว่า TypeScript คืออะไร ผมคงตอบไปสั้นๆ ว่า คือการเอา static type มาใส่เข้าไปใน JavaScript นั่นเอง
ลองดูตัวอย่างนี้ เช่น มี function สำหรับเพิ่มค่าตัวเลข ถ้าเป็น Javascript เราจำเป็นที่จะต้องตรวจสอบ type ก่อน เพื่อป้องกันการเกิด error
// app.js
let counter = 10;
function increateCounter() {
if (typeof counter === 'number') {
counter += 1;
} else {
throw new Error('counter is not a number');
}
}
แต่ถ้าใช้ TypeScript เราไม่ต้องตรวจสอบ type เองแล้ว
let counter: number = 10;
function increateCounter() {
counter += 1;
}
ชีวิตดูดีขึ้นเยอะ 👍
มาทำความรู้จัก Type กันก่อน 😏
มาลองดูกันว่า TypeScript มีชนิดข้อมูลแบบไหนบ้าง
1. Predefined Types
เป็นชนิดของข้อมูลที่ถูกเตรียมไว้ให้แล้ว โดยขอเริ่มจของ JavaScript ซึ่งที่ใช้งานบ่อยๆ นั้นก็จะมีประมาณนี้
- String
- Number
- Boolean
- Array
- Function
- Object
และส่วนที่เพิ่มเข้ามาจาก TypeScript มีดังนี้
- Any - ถ้าไม่รู้จะใส่ type อะไร ให้ใส่ตัวนี้ไปเลย และมันก็จะไปปิดการทำ type checking
- Tuple - คือ Array ที่ต้องระบุขนาดตายตัว และต้องกำหนดกำหนดชนิดข้อมูลให้แต่ละ elements ด้วย เช่น
let rgbColor = [number, number, number];
- Enum - ใช้กำหนดชื่อให้กับค่าชุดหนึ่งได้ โดยค่าจะเริ่มจาก 0 เช่น
enum ArrowKeys {
Up, // 0
Down, // 1
Left, // 2
Right, // 3
}
// หรือจะกำหนดค่าเองก็ได้
enum ArrowKeys {
Up = 'up',
Down = 'down',
Left = 'left',
Right = 'right',
}
ยังมีอีกหลาย type แต่เอาเท่าที่ใช้งานบ่อยๆ ก่อน
วิธีกำหนดชนิดข้อมูลให้กับตัวแปร
ิวิธีกำหนดนั้นง่ายมาก เพียงแค่ใส่ :type
หลังชื่อตัวแปรก็ได้แล้ว
- เริ่มจากชนิดข้อมูลพื้นฐานก่อน String, Number และ Boolean
// javascript
let name = 'Stamp';
let age = 5;
let isSterilized = true;
เมื่อเขียนแบบ TypeScript
// typescript
let name: string = 'Stamp';
let age: number = 5;
let isSterilized: boolean = true;
- Array บอกไว้ก่อนไม่ได้ใช้
:array
นะ 😆
// javascript
let favoriteFoods = ['Chicken', 'Corn', 'Strawberry'];
เมื่อเขียนแบบ TypeScript ให้ดูว่าข้อมูลใน array เป็นอะไร ก็ใช้ type แล้วตาม []
// typescript
let favoriteFoods: string[] = ['Chicken', 'Corn', 'Strawberry'];
- Function จะมีกำหนดอยู่ 2 ส่วน คือ 1. ตรง parameter และ 2. ค่าที่ต้อง return กลับไป
// javascript
let generateFullName = (firstName, lastName) => {
return firstName + ' ' + lastName;
};
เมื่อเขียนแบบ TypeScript
// typescript
let generateFullName = (firstName: string, lastName: string): string => {
return firstName + ' ' + lastName;
};
- Object
// javascript
let dog = {
name: 'Stamp',
age: 5,
gender: 'male',
isSterilized: true,
favoriteFoods: ['Chicken', 'Corn', 'Strawberry'],
};
เมื่อเขียนแบบ TypeScript ก็กำหนดลงไปตรงๆ หลังชื่อตัวแปรได้เลย (ใช้ ;
นะ)
// typescript
let dog: {
name: string;
age: number;
gender: string;
isSterilized: boolean;
favoriteFoods: string[];
} = {
name: 'Stamp',
age: 5,
gender: 'male',
isSterilized: true,
favoriteFoods: ['Chicken', 'Corn', 'Strawberry'],
};
2.Custom Type
จากการกำหนด type ของ object แบบข้างบนนั้น ถ้าเรามี dog2 ก็ต้องมากำหนด type แบบนี้ซ้ำขึ้น ทำให้ขาดความ reuseable ไปดังนั้นเราจำเป็นที่จะต้องสร้าง custom type ขึ้นมาเอง โดยการใช้ type
และ interface
แล้ว type คืออะไร 🤨
type
นั้นเป็นการสร้าง alias type ขึ้นมาเพื่อบอกว่า type นั้นๆ ควรมีหน้าตาเป็นยังไง เช่น gender
นั้นสามารถระบุได้แค่ male
กับ female
เท่านั้น เราก็สามารถสร้างเป็น genderType
ขึ้นมาได้เพื่อให้ระบุได้เฉพาะ สองค่านี้เท่านั้น ทำได้โดย
type genderType = 'male';
let gender: genderType = 'male';
แต่ถ้าลองกำหนด let gender: genderType = 'female';
แบบนี้จะยังทำไม่ได้ เราจะต้องใช้ Union Operater มาช่วยในการสร้าง type ให้สมบูรณ์
type genderType = 'male' | 'female';
let gender: genderType = 'female';
แล้ว interface มีไว้ทำไม😅
เจ้า interface นี่คือเอาไว้กำหนดหว่า Object นั้นๆ จะมีหน้าตาเป็นยังไง
โดยจะเอาตัวอย่างข้างบน มาสร้าง interface ดู
// typescript
interface Dog {
name: string;
age: number;
gender: string;
isSterilized: boolean;
favoriteFoods: string[];
}
let dog: Dog = {
name: 'Stamp',
age: 5,
gender: 'male',
isSterilized: true,
favoriteFoods: ['Chicken', 'Corn', 'Strawberry'],
};
และเรายังสามารถใช้ type และ interface ร่วมกันได้ แบบนี้
// typescript
type genderType = 'male' | 'female';
interface Dog {
name: string;
age: number;
gender: genderType;
isSterilized: boolean;
favoriteFoods: string[];
}
let dog: Dog = {
name: 'Stamp',
age: 5,
gender: 'male',
isSterilized: true,
favoriteFoods: ['Chicken', 'Corn', 'Strawberry'],
};
คร่าวนี้ก็วามารถ reuse การสร้าง Object ของ dog ได้แล้ว 🎉
3. Type Assertion
ในบางกรณีเราอาจสร้าง object เปล่าแบบนี้ let dog = {};
ซึ่ง TypeScript จะไม่รู้จักว่า Object นี่คือ type อะไร มี property อะไรบ้าง
let dog = {};
dog.name = 'Snow'; // Property 'name' does not exist on type '{}'.
ทำให้เราไม่สามารถกำหนดค่า property ให้กับ dog ได้ เพราะ TypeScript ไม่รู้จัก
แต่สามารถแก้ได้โดยการใช้ as
ดังนี้
let dog = {} as Dog; // ใช้ as เพื่อบอกชนิดของ object
dog.name = 'Snow';
dog.age = 5;
dog.gender = 'female';
dog.isSterilized = true;
dog.favoriteFoods = ['Chicken', 'Corn', 'Strawberry'];
แบบนี้ TypeScript ก็รู้แล้วว่าเป็น Dog
4. Generic Type
มาถึงตัวสุดท้ายของบทความนี้แล้ว
งั้นขออธิบายจากโค้ดเลยละกัน
ตัวอย่างเช่น มีฟังก์ชัน createNumberList
และ createStringList
function createNumberList(item: number): number[] {
const newList: number[] = [];
newList.push(item);
return newList;
}
function createStringList(item: string): string[] {
const newList: string[] = [];
newList.push(item);
return newList;
}
const numberList = createNumberList(123);
const stringList = createNumberList('abc');
จะเห็นว่าทั้ง 2 ฟังก์ชันนั้นทำงานเหมือนกันเลย แต่ต่างกันแค่ชนิดของข้อมูล เราจะทำยังไงให้มัน reuseable ได้ โดยให้เหลือแค่ฟังก์ชัน createList เท่านั้น
ในการทำแบบนี้เราจะใช้ Generic Type เข้ามาช่วย แบบนี้
function createList<CustomType>(item: CustomType): CustomType[] {
const newList: CustomType[] = [];
newList.push(item);
return newList;
}
const numberList = createList<number>(123);
const stringList = createList<string>('abc');
ตรงคำว่า CustomType
นั่นด็คือ Generic จริงๆ แล้วจะใช้ชื่ออะไรก็ได้ แต่โดยทั่วไปจะใช้ตัว T
กัน แบบนี้
function createList<T>(item: T): T[] {
const newList: T[] = [];
newList.push(item);
return newList;
}
const numberList = createList<number>(123);
const stringList = createList<string>('abc');
ซึ่งจะเห็นว่าการใช้งาน Generic Type นั้นจะช่วยให้โค้ดของเราสามารถ reuseable ได้แล้ว
จริงๆ แล้ว TypeScript นั้นยังมีเนื้อหาอีกเยอะ แต่คิดว่าเมื่อเข้าใจเรื่อง Type ในบทความนี้ดีแล้ว ก็น่าจะเริ่มเขียน TypeScript ได้แล้วหล่ะครับ ^^
Top comments (0)