타입 안전한 emit과 on
이벤트를 발생시키고 수신할 때 올바른 페이로드를 강제합니다.
타입 안전한 emit과 on은(는) CoddyKit의 무료 TypeScript Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 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이므로 맵에 없는 이벤트를 emit할 수 없습니다.
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을 사용하는 타입 지정 핸들러
on 메서드는 인수가 정확히 Events[K]인 핸들러를 등록하므로, 핸들러가 올바른 타입의 페이로드를 받습니다.
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은 함께 타입이 지정된 발행 및 구독 기능을 구성합니다. 이벤트를 발생시키면 올바른 타입의 페이로드가 해당 핸들러에 전달됩니다.
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 및 이벤트 등록
페이로드가 Events[K]인 제네릭 emit 및 on 시그니처를 만들었습니다. 따라서 이벤트 이름은 자동 완성되고, 잘못된 페이로드는 컴파일 오류가 되며, 핸들러 인수는 추론됩니다.
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” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 TypeScript Academy 강의 전체를 잠금 해제할 수 있습니다. TypeScript Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“타입 안전한 emit과 on”에서 뭘 배우나요?
이벤트를 발생시키고 수신할 때 올바른 페이로드를 강제합니다. 브라우저에서 직접 실행하는 실습 코드로 TypeScript Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
TypeScript Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 TypeScript Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“타입 안전한 emit과 on” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 TypeScript Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 TypeScript Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 이벤트 맵에 타입 지정하기
- 타입 안전한 emit과 on
- 제네릭 이벤트 이미터 클래스
- 리스너 인수 추론