- 문자열 템플릿 리터럴 타입을 이용하면 유연성을 유지하면서도 문자열 리터럴을 정의할 수 있다.
- 템플릿 리터럴 타입을 이용해 사용자 정의 이벤트 시스템을 만들 때 모든 이벤트명을 “on”으로 시작하도록 이름 규칙을 정할 수 있다. (빈 문자열 포함)
type EventName = `on${string}`;
- HTML의 헤딩 요소를 표현하는 문자열 타입을 정의할 수 있다.
type Levels = 1 | 2 | 3 | 4 | 5 | 6;
// "H1" | "H2" | "H3" | "H4" | "H5" | "H6"
type Headings = `H${Levels}`;
- 한 개의 매개변수 EventObject를 갖는 Callback 함수 타입을 정의한다. EventObject는 이벤트 정보의 값을 포함하는 제네릭 타입이다.
- 모든 등록된 이벤트 콜백을 저장할 Events 타입을 정의한다. EventName은 string의 유효한 하위 집합이므로 이를 인덱스 접근자로 사용한다.
type EventName = `on${string}`;
type EventObject<T> = {
val: T;
}
type Callback<T = any> = (e: EventObject<T>) => void;
type Events = {
[x: EventName]: Callback[] | undefined;
}
- EventSystem 클래스를 정의한다. 생성자는 새 이벤트 저장소를 만들고 defineEventHandler는 EventName과 Callback을 인수로 받아 이벤트 저장소에 저장한다. Trigger는 EventName을 인수로 받아 콜백이 등록되었다면 EventObject로 모든 등록된 콜백을 실행한다.
class EventSystem {
events: Events;
constructor() {
this.events = {};
}
defineEventHandler(ev: EventName, cb: Callback): void {
this.events[ev] = this.events[ev] ?? [];
this.events[ev]?.push(cb);
}
trigger(ev: EventName, value: any) {
let callbacks = this.events[ev];
if (callbacks) {
callbacks.forEach((cb) => {
cb({ val: value });
})
}
}
}
const system = new EventSystem();
system.defineEventHandler('onClick', () => {});