สวัสดีครับในบทความนี้เราจะมาเรียนรู้การใช้งาน Generic Type ใน TypeScript กันครับ
สำหรับภาษาทางด้าน Programming ที่จะต้องระบุ Type หรือชนิดของข้อมูล อย่าง C#, Java, ฯลฯ รวมไปถึง TypeScript ด้วย ในทุกๆครั้งที่เราประกาศตัวแปรขึ้นมาใช้งาน เราจําเป็นต้องระบุ Type หรือชนิดของข้อมูลทุกครั้ง
Generic Type จะมีประโยชน์ในการณีที่เราต้องการสร้าง Function, Class, Method ฯลฯ ที่เป็น Dynamic type ที่ผู้ใช้งานสามารถระบุ Type ที่จะทํางานเข้าไปตอนใช้งานได้ เพื่อให้เข้าในการทํางานมากขึ้นมาดูตัวอย่างแบบง่ายๆดังนี้
function identity(arg: number): number {
return arg;
}
ปกติเวลาเราสร้าง Function ขึ้นมาใช้งานเราจะสร้างแบบ Code ด้านบน ซึ่งจะเห็นว่า Type ของข้อมูลที่รับเข้ามาจะถูกกําหนดเป็น number เท่านั้น หมายความว่าถ้าเราจะไม่สามารถจะนำ Function นี้ไปใช้กับ Type อื่นๆได้เลย
ถ้าเราต้องการให้ Function นี้สามารถใช้งานกับ Type อื่นๆได้ตามที่ ผู้ใช้งานระบุ เราจึงใช้ Generic Type เข้ามาช่วย โดยสามารถเขียนได้ดังนี้
function identity<T>(arg: T): T {
return arg;
}
// สามารถใช้งานได้แบบนี้
const a = identity<string>('My string'); // a จะมี Type เป็น string
const b = identity('My string'); // b จะมี Type เป็น string
const c = identity<number>(100); // c จะมี Type เป็น number
const d = identity(100); // d จะมี Type เป็น number
จากตัวอย่างด้านบน เราสามารถใช้ "
Note: “T” สามารถเปลี่ยนเป็น Wording อื่นๆได้ ไม่จําเป็นต้องเป็น “T” เพียงอย่างเดียว
นอกเหนือจากนี้คุณสามารถเปลี่ยน “identity” Function ด้านบนไปเป็น Interface ได้ตามตัวอย่างนี้ครับ
interface GenericIdentityFn {
<Type>(arg: Type): Type;
}
function identity<Type>(arg: Type): Type {
return arg;
}
let myIdentity: GenericIdentityFn = identity;
Generic Class ก็ใช้งานคือระบุไว้ใน ”<>” เช่นเดียวกันครับ มาดูตัวอย่างกันดังนี้
class GenericNumber<NumType> {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
return x + y;
};
console.log(myGenericNumber.add(myGenericNumber.zeroValue, 100));
// More Example
let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = '0';
stringNumeric.add = function (x, y) {
const numX = +x; // Convert string to number
const numY = +y; // Convert string to number
return numX + numY;
};
console.log(stringNumeric.add(stringNumeric.zeroValue, '100'));
จากตัวอย่างด้านบน เราสามารถสร้าง Class ที่เป็น Generic Type ซึ่งจะสามารถทํางานกับ Type อื่นๆ ได้ตามที่ผู้ใช้งาน Class กําหนด
สําหรับการทํางานบางอย่างเราอาจจะต้องการที่จะระบุลงลึกไปอีกว่า Class หรือ function ที่เราจะสร้างขึ้นมานั้นจะต้องการ Type เป็นแบบใดยกตัวอย่างเช่น ถ้าเราต้องการสร้าง Funvtion ที่เอาไว้หา Length เราก็สามารถระบุไปแบบนี้ได้ครับ
interface Lengthwise {
length: number;
}
function loggingIdentity<Type extends Lengthwise>(arg: Type): Type {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
// ตอนใช้งานจะรับเฉพาะ Paramiter type ที่มี property เป็น "length"
loggingIdentity({ length: 10, value: 3 }); // No Error
loggingIdentity('my string'); // No Error
loggingIdentity(100); // Error เพราะว่า type number ไม่มี property length
เราสามารใช้ Type Parameters ใน Generic Constraints ตัวอย่างเช่นถ้าเราต้องการจะให้แน่ใจว่า ผู้ที่นํา Class หรือ Function ไปใช้งานจะระบุ propery หรือค่าบางอย่างมาถูกต้อง มาดูตัวอย่างกันครับ
function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, 'a');
getProperty(x, 'm'); // Error เพราะ property "m" ไม่มีใน x
เราสามารถกำหนด Class type ใน Generic ได้ ตามตัวอย่างนี้ครับ
class BeeKeeper {
hasMask: boolean = true;
}
class ZooKeeper {
nametag: string = 'Mikle';
}
class Animal {
numLegs: number = 4;
}
class Bee extends Animal {
numLegs = 6;
keeper: BeeKeeper = new BeeKeeper();
}
class Lion extends Animal {
keeper: ZooKeeper = new ZooKeeper();
}
function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}
createInstance(Lion).keeper.nametag;
createInstance(Bee).keeper.hasMask; ในงานด้าน hardware ที่มีการอ่านข้อมูลจาก sensor แน่นอนว่าข้อมูลที่ได้มาในแต่ละครั้งอาจจะมีข้อมูลที่ error หรือข้อมูลที่เพี้ยนไปจากความเป็นจริงบางช่วงเวลา ซึ่งเราไม่ต้องการข้อมูลพวกนั้นเช่น ถ้าเราต้องการวนลูปอ่านข้อมูลจาก Accelerometer เป็น sensor วัดความเร่ง ปกติแล้วเมื่อเราวนลูปอ่านข้อมูลจาก sensor พวกนี้จะได้ค่า error หรือสัญญานรบกวน ค่อนข่างสูง
Unicode คือ รหัสข้อมูลทางคอมพิวเตอร์ที่ใช้แทนอักขระ สามารถใช้แทนตัวอักษร ตัวเลข และสัญลักษณ์ต่างๆ ได้มากกว่า ASCII ซึ่งแทนอักขระได้แค่ 256 ตัวเท่านั้น(1Byte) Unicode สามารถใช้แทนตัวอักษร จากภาษาทั้งหมดทั่วโลก 24 ภาษา
IPFS ย่อมาจาก Interplanetary File System เป็นเว็บแบบกระจายตัว หรือ Decentralized Content Gateway และ IPFS เป็นระบบไฟล์แบบ peer-to-peer คล้ายๆ Blockchain โดยจะกระจายไฟล์ไปเก็บไว้ยังเครื่องคอมพิวเตอร์ที่ทําหน้าที่เป็น Node ทั่วโลก แทนที่จะเก็ไฟล์ไว้ใน Server หรือคอมพิวเตอร์เพียงเครื่องเดียว ทําให้ไฟล์ยังคงอยู่ตลอดไปตามใดที่ยังมีคนสนใจไฟล์นั้น และเก็บไฟล์นั้นไว้