0Pricing
TypeScript Academy · บทเรียน

emit และ on ที่ปลอดภัยด้านชนิดข้อมูล

บังคับใช้ส่วนข้อมูลที่ถูกต้องเมื่อส่งเหตุการณ์และรับฟังเหตุการณ์

emit และ on ที่ปลอดภัยด้านชนิดข้อมูล เป็นบทเรียน TypeScript Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน TypeScript Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส TypeScript Academy มีบทเรียนทั้งหมด 4 บทเรียน

ลายเซ็น emit ที่ปลอดภัยด้านชนิดข้อมูล

ทำให้ emit เป็นแบบทั่วไปเหนือชื่อเหตุการณ์ K จากนั้นพารามิเตอร์ข้อมูลประกอบจะเป็น Events[K] ทำให้ชื่อเหตุการณ์และข้อมูลประกอบต้องตรงกัน

interface Events { login: { userId: string }; logout: void }
function emit<K extends keyof Events>(event: K, payload: Events[K]) {
  console.log("emit", event, JSON.stringify(payload));
}
emit("login", { userId: "u1" });

ข้อมูลประกอบไม่ถูกต้องจะเป็นข้อผิดพลาดขณะคอมไพล์

หากข้อมูลประกอบไม่ตรงกับชื่อเหตุการณ์ TypeScript จะปฏิเสธข้อมูลนั้น ชนิดข้อมูลแบบทั่วไปจะเชื่อมพารามิเตอร์ทั้งสองเข้าด้วยกัน

interface Events { login: { userId: string } }
function emit<K extends keyof Events>(event: K, payload: Events[K]) {}
// emit("login", { id: "u1" }); // Error: id is not userId
emit("login", { userId: "u1" });
console.log("ok");

ชื่อเหตุการณ์ที่ไม่รู้จักจะถูกปฏิเสธ

เนื่องจาก K extends keyof Events คุณจึงไม่สามารถส่งเหตุการณ์ที่ไม่มีอยู่ในแผนผังได้

interface Events { login: { userId: string } }
function emit<K extends keyof Events>(event: K, payload: Events[K]) {}
// emit("signup", { userId: "x" }); // Error: "signup" not a key
emit("login", { userId: "x" });
console.log("only known events");

ตัวจัดการที่มีชนิดข้อมูลด้วยการสมัครรับเหตุการณ์

เมธอด on จะลงทะเบียนตัวจัดการที่มีอาร์กิวเมนต์เป็น Events[K] อย่างตรงตัว ดังนั้น handlers จึงได้รับข้อมูลประกอบที่มีชนิดข้อมูลถูกต้อง

interface Events { login: { userId: string }; logout: void }
function on<K extends keyof Events>(event: K, handler: (payload: Events[K]) => void) {
  console.log("subscribed to", event);
}
on("login", (p) => console.log(p.userId));

ระบบอนุมานอาร์กิวเมนต์ของตัวจัดการ

คุณไม่ต้องใส่คำอธิบายชนิดข้อมูลให้พารามิเตอร์ของตัวจัดการ เพราะ TypeScript จะอนุมานชนิดข้อมูลจากชื่อเหตุการณ์ ทำให้ใช้การเติมข้อความอัตโนมัติภายในเนื้อหาของตัวจัดการได้อย่างครบถ้วน

interface Events { message: { text: string } }
function on<K extends keyof Events>(event: K, handler: (p: Events[K]) => void) {}
on("message", (p) => {
  // p is { text: string }
  console.log(p.text.toUpperCase());
});

การจัดการเหตุการณ์ที่ไม่มีข้อมูลประกอบ

สำหรับเหตุการณ์ void ตัวจัดการจะรับอาร์กิวเมนต์ที่ไม่มีประโยชน์ใด ๆ เพียงตัวเดียว คุณสามารถเรียกตัวจัดการโดยไม่ส่งข้อมูลได้

interface Events { logout: void }
function on<K extends keyof Events>(event: K, handler: (p: Events[K]) => void) {}
on("logout", () => console.log("logged out"));

การทำงานร่วมกันของ emit และการสมัครรับเหตุการณ์

เมื่อทำงานร่วมกัน emit และ on จะเป็นระบบเผยแพร่และสมัครรับข้อมูลที่มีชนิดข้อมูล การส่งเหตุการณ์จะส่งข้อมูลประกอบที่มีชนิดข้อมูลถูกต้องไปยัง handlers

interface Events { ping: { at: number } }
type Handler<K extends keyof Events> = (p: Events[K]) => void;
const handlers: { ping: Handler<"ping">[] } = { ping: [] };
function on<K extends keyof Events>(e: K, h: Handler<K>) { handlers[e].push(h as Handler<"ping">); }
function emit<K extends keyof Events>(e: K, p: Events[K]) { handlers[e].forEach(h => h(p as Events["ping"])); }
on("ping", p => console.log("at", p.at));
emit("ping", { at: 5 });

การจำกัดตำแหน่งข้อมูลประกอบ

ชนิดข้อมูลแบบทั่วไปจะตรวจสอบว่าอาร์กิวเมนต์ข้อมูลประกอบตรงกับเหตุการณ์ที่เลือก ทำให้ตรวจพบความไม่ตรงกันตั้งแต่ตำแหน่งที่เรียกใช้ ไม่ใช่ลึกเข้าไปในตัวจัดการ

interface Events { add: { x: number; y: number } }
function emit<K extends keyof Events>(e: K, p: Events[K]) {
  return e;
}
emit("add", { x: 1, y: 2 });
// emit("add", { x: 1 }); // Error: y missing
console.log("payload checked");

การเติมชื่อเหตุการณ์อัตโนมัติ

เนื่องจากพารามิเตอร์แรกเป็น keyof Events เครื่องมือแก้ไขจึงเติมชื่อเหตุการณ์ที่ถูกต้องโดยอัตโนมัติขณะที่คุณพิมพ์การเรียกใช้

interface Events { open: void; close: void }
function emit<K extends keyof Events>(e: K, p: Events[K]) {}
// Typing emit(" suggests "open" and "close"
emit("open", undefined as void);
console.log("autocompleted names");

เหตุผลที่ชนิดข้อมูลแบบทั่วไปจำเป็นที่นี่

หากไม่มีชนิดข้อมูลแบบทั่วไป คุณจะต้องสร้างลายเซ็นหลายรูปแบบสำหรับทุกเหตุการณ์ ลายเซ็นแบบทั่วไปเพียงหนึ่งรูปแบบรองรับเหตุการณ์จำนวนเท่าใดก็ได้โดยอัตโนมัติ

interface Events { a: { x: number }; b: { y: string } }
function emit<K extends keyof Events>(e: K, p: Events[K]) { return p; }
console.log(emit("a", { x: 1 }), emit("b", { y: "hi" }));

รูปแบบที่นำกลับมาใช้ใหม่ได้

รูปแบบ emit<K>(event, payload) และ on<K>(event, handler) นี้เป็นแกนหลักของตัวส่งเหตุการณ์ที่ปลอดภัยด้านชนิดข้อมูลทุกชนิด ซึ่งเราจะรวมเป็นคลาสในบทถัดไป

interface Events { tick: { n: number } }
function emit<K extends keyof Events>(e: K, p: Events[K]) { return e; }
function on<K extends keyof Events>(e: K, h: (p: Events[K]) => void) { return e; }
console.log(emit("tick", { n: 1 }), on("tick", p => p.n));

ตรวจสอบความเข้าใจอย่างรวดเร็ว: emit และการสมัครรับเหตุการณ์แบบมีชนิดข้อมูล

ทดสอบความเข้าใจเกี่ยวกับ emit และการสมัครรับเหตุการณ์ที่ปลอดภัยด้านชนิดข้อมูล

สรุป: emit และการสมัครรับเหตุการณ์ที่ปลอดภัยด้านชนิดข้อมูล

คุณสร้างลายเซ็นแบบทั่วไปสำหรับ emit และ on โดยข้อมูลประกอบเป็น Events[K] ดังนั้นชื่อเหตุการณ์จึงเติมข้อความอัตโนมัติได้ ข้อมูลประกอบที่ไม่ถูกต้องจะเป็นข้อผิดพลาดขณะคอมไพล์ และระบบจะอนุมานอาร์กิวเมนต์ของตัวจัดการให้

interface Events { login: { userId: string } }
function emit<K extends keyof Events>(e: K, p: Events[K]) { return e; }
console.log(emit("login", { userId: "u1" }));

คำถามที่พบบ่อย

บทเรียน “emit และ on ที่ปลอดภัยด้านชนิดข้อมูล” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “emit และ on ที่ปลอดภัยด้านชนิดข้อมูล” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส TypeScript Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส TypeScript Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “emit และ on ที่ปลอดภัยด้านชนิดข้อมูล”

บังคับใช้ส่วนข้อมูลที่ถูกต้องเมื่อส่งเหตุการณ์และรับฟังเหตุการณ์ คุณปฏิบัติ TypeScript Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน TypeScript Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน TypeScript Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “emit และ on ที่ปลอดภัยด้านชนิดข้อมูล” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน TypeScript Academy นี้ได้ไหม

ได้ บทเรียน TypeScript Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การกำหนดชนิดข้อมูลให้แผนผังเหตุการณ์
  2. emit และ on ที่ปลอดภัยด้านชนิดข้อมูล
  3. คลาสตัวส่งเหตุการณ์แบบเจเนอริก
  4. การอนุมานอาร์กิวเมนต์ของตัวรับฟัง
← กลับไปที่ TypeScript Academy