제네릭 이벤트 이미터 클래스
재사용 가능한 타입 지정 이벤트 이미터를 처음부터 구축합니다.
제네릭 이벤트 이미터 클래스은(는) CoddyKit의 무료 TypeScript Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 TypeScript Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. TypeScript Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
목표: TypedEmitter 클래스
이벤트 맵 E를 기준으로 제네릭화된 재사용 가능한 TypedEmitter<E> 클래스를 만들고, 타입이 완전히 지정된 on, off, emit 메서드를 구현합니다.
interface Events { login: { userId: string }; logout: void }
// class TypedEmitter<Events> will manage handlers safely.
console.log("building a typed emitter");핸들러 타입 별칭
각 리스너가 올바른 페이로드를 받도록 이벤트 이름을 매개변수로 사용하는 핸들러 타입을 정의합니다.
type Handler<E, K extends keyof E> = (payload: E[K]) => void;
// E[K] is the payload type for event K in map E.
console.log("handler typed by E[K]");listeners 맵
이벤트 이름을 키로 하여 핸들러를 저장합니다. 매핑된 타입을 사용하면 각 키가 올바른 타입의 핸들러 배열을 갖게 됩니다.
class TypedEmitter<E> {
private listeners: { [K in keyof E]?: Array<(p: E[K]) => void> } = {};
}
console.log("listeners map ready");이벤트 등록 구현
on 메서드는 해당 이벤트의 배열에 핸들러를 추가하며, 처음 사용할 때 배열을 만듭니다.
class TypedEmitter<E> {
private listeners: { [K in keyof E]?: Array<(p: E[K]) => void> } = {};
on<K extends keyof E>(event: K, handler: (p: E[K]) => void): void {
(this.listeners[event] ||= []).push(handler);
}
}
console.log("on implemented");emit 구현
emit 메서드는 이벤트에 해당하는 핸들러를 조회하고 타입이 지정된 페이로드를 각 핸들러에 전달하여 호출합니다.
class TypedEmitter<E> {
private listeners: { [K in keyof E]?: Array<(p: E[K]) => void> } = {};
on<K extends keyof E>(e: K, h: (p: E[K]) => void) { (this.listeners[e] ||= []).push(h); }
emit<K extends keyof E>(e: K, payload: E[K]): void {
(this.listeners[e] || []).forEach(h => h(payload));
}
}
console.log("emit implemented");이벤트 등록 해제 구현
off 메서드는 배열에서 이전에 등록된 핸들러를 필터링하여 제거합니다.
class TypedEmitter<E> {
private listeners: { [K in keyof E]?: Array<(p: E[K]) => void> } = {};
on<K extends keyof E>(e: K, h: (p: E[K]) => void) { (this.listeners[e] ||= []).push(h); }
off<K extends keyof E>(e: K, h: (p: E[K]) => void) {
this.listeners[e] = (this.listeners[e] || []).filter(x => x !== h);
}
}
console.log("off implemented");클래스 완성하기
다음은 사용자가 제공하는 모든 이벤트 맵에 대해 제네릭화된 세 가지 메서드를 포함한 전체 클래스입니다.
class TypedEmitter<E> {
private listeners: { [K in keyof E]?: Array<(p: E[K]) => void> } = {};
on<K extends keyof E>(e: K, h: (p: E[K]) => void) { (this.listeners[e] ||= []).push(h); }
off<K extends keyof E>(e: K, h: (p: E[K]) => void) { this.listeners[e] = (this.listeners[e] || []).filter(x => x !== h); }
emit<K extends keyof E>(e: K, p: E[K]) { (this.listeners[e] || []).forEach(h => h(p)); }
}
console.log("TypedEmitter complete");TypedEmitter 사용하기
구체적인 이벤트 맵을 사용하여 인스턴스를 만드십시오. 이제 해당 이벤트에 대해 on과 emit의 타입이 완전히 지정됩니다.
class TypedEmitter<E> {
private listeners: { [K in keyof E]?: Array<(p: E[K]) => void> } = {};
on<K extends keyof E>(e: K, h: (p: E[K]) => void) { (this.listeners[e] ||= []).push(h); }
emit<K extends keyof E>(e: K, p: E[K]) { (this.listeners[e] || []).forEach(h => h(p)); }
}
interface Events { login: { userId: string } }
const bus = new TypedEmitter<Events>();
bus.on("login", p => console.log("hi", p.userId));
bus.emit("login", { userId: "u1" });타입 오류가 발견됩니다
이 클래스는 독립 실행형 함수와 마찬가지로 컴파일 시점에 알 수 없는 이벤트와 잘못된 페이로드를 거부합니다.
class TypedEmitter<E> {
private listeners: { [K in keyof E]?: Array<(p: E[K]) => void> } = {};
on<K extends keyof E>(e: K, h: (p: E[K]) => void) { (this.listeners[e] ||= []).push(h); }
emit<K extends keyof E>(e: K, p: E[K]) { (this.listeners[e] || []).forEach(h => h(p)); }
}
interface Events { ping: { at: number } }
const bus = new TypedEmitter<Events>();
// bus.emit("pong", { at: 1 }); // Error
bus.emit("ping", { at: 1 });
console.log("typed bus");이벤트마다 여러 handlers 사용하기
각 이벤트가 배열에 매핑되므로 여러 핸들러를 등록할 수 있으며, emit할 때 모두 실행됩니다.
class TypedEmitter<E> {
private listeners: { [K in keyof E]?: Array<(p: E[K]) => void> } = {};
on<K extends keyof E>(e: K, h: (p: E[K]) => void) { (this.listeners[e] ||= []).push(h); }
emit<K extends keyof E>(e: K, p: E[K]) { (this.listeners[e] || []).forEach(h => h(p)); }
}
interface Events { tick: { n: number } }
const bus = new TypedEmitter<Events>();
bus.on("tick", p => console.log("a", p.n));
bus.on("tick", p => console.log("b", p.n));
bus.emit("tick", { n: 7 });확장할 수 있는 기반
이 클래스는 견고한 기반입니다. 다음에는 리스너 인수 추론을 개선하고 once 동작을 추가하겠습니다.
class TypedEmitter<E> {
private listeners: { [K in keyof E]?: Array<(p: E[K]) => void> } = {};
on<K extends keyof E>(e: K, h: (p: E[K]) => void) { (this.listeners[e] ||= []).push(h); }
emit<K extends keyof E>(e: K, p: E[K]) { (this.listeners[e] || []).forEach(h => h(p)); }
}
const bus = new TypedEmitter<{ go: void }>();
bus.on("go", () => console.log("go!"));
bus.emit("go", undefined as void);빠른 확인: 제네릭 이미터 클래스
제네릭 이벤트 이미터 클래스에 대한 이해도를 확인해 보십시오.
복습: 제네릭 이벤트 이미터 클래스
매핑된 listeners 저장소와 타입이 완전히 지정된 on, off, emit 메서드를 갖춘 TypedEmitter<E>를 만들었습니다. 이를 통해 모든 이벤트 맵에 사용할 수 있는 재사용 가능하고 타입 안전한 발행 및 구독 기능을 구현했습니다.
class TypedEmitter<E> {
private listeners: { [K in keyof E]?: Array<(p: E[K]) => void> } = {};
on<K extends keyof E>(e: K, h: (p: E[K]) => void) { (this.listeners[e] ||= []).push(h); }
emit<K extends keyof E>(e: K, p: E[K]) { (this.listeners[e] || []).forEach(h => h(p)); }
}
const bus = new TypedEmitter<{ hi: { name: string } }>();
bus.on("hi", p => console.log(p.name));
bus.emit("hi", { name: "Ada" });AI 튜터와 함께 TypeScript을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 101
- 레슨
- 352
자주 묻는 질문
“제네릭 이벤트 이미터 클래스” 강의는 무료인가요?
네 — “제네릭 이벤트 이미터 클래스” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 TypeScript Academy 강의 전체를 잠금 해제할 수 있습니다. TypeScript Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“제네릭 이벤트 이미터 클래스”에서 뭘 배우나요?
재사용 가능한 타입 지정 이벤트 이미터를 처음부터 구축합니다. 브라우저에서 직접 실행하는 실습 코드로 TypeScript Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
TypeScript Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 TypeScript Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“제네릭 이벤트 이미터 클래스” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 TypeScript Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 TypeScript Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 이벤트 맵에 타입 지정하기
- 타입 안전한 emit과 on
- 제네릭 이벤트 이미터 클래스
- 리스너 인수 추론