# 생성자에서 타입정의

일반적인 Node.js와 전통 JavaScript에서는 단일 이벤트 출력기를 사용합니다. 이 이벤트 출력기는 내부적으로 여러 이벤트 종류에 대한 리스너를 관리합니다. 예를 들어:

```typescript
const emitter = new EventEmitter();
// Emit: 
emitter.emit('foo', foo);
emitter.emit('bar', bar);
// Listen: 
emitter.on('foo', (foo)=>console.log(foo));
emitter.on('bar', (bar)=>console.log(bar));
```

기본적으로 `EventEmitter` 내부에는 데이터가 매핑된 배열로 저장됩니다:

```typescript
{foo: [fooListeners], bar: [barListeners]}
```

대신, 순전히 *이벤트* 타입 안전성을 위해 이벤트 타입별로 출력기를 만들 수도 있습니다:

```typescript
const onFoo = new TypedEvent<Foo>();
const onBar = new TypedEvent<Bar>();

// Emit: 
onFoo.emit(foo);
onBar.emit(bar);
// Listen: 
onFoo.on((foo)=>console.log(foo));
onBar.on((bar)=>console.log(bar));
```

이렇게 하면 다음과 같은 장점이 있습니다:

* 이벤트의 타입이 변수 값을 통해 쉽게 파악됨.
* 이벤트 출력기 변수를 독립적으로 손쉽게 리팩토링할 수 있음.
* 이벤트 자료 구조의 타입 안전성.

## TypedEvent 예시

```typescript
export interface Listener<T> {
  (event: T): any;
}

export interface Disposable {
  dispose();
}

/** 발생하는 이벤트를 지켜봄. 리스닝을 시작하기 전에 발생한 이벤트는 받지 못함 */
export class TypedEvent<T> {
  private listeners: Listener<T>[] = [];
  private listenersOncer: Listener<T>[] = [];

  on = (listener: Listener<T>): Disposable => {
    this.listeners.push(listener);
    return {
      dispose: () => this.off(listener)
    };
  }

  once = (listener: Listener<T>): void => {
    this.listenersOncer.push(listener);
  }

  off = (listener: Listener<T>) => {
    var callbackIndex = this.listeners.indexOf(listener);
    if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1);
  }

  emit = (event: T) => {
    /** 범용 리스너 모두에게 알림 */
    this.listeners.forEach((listener) => listener(event));

    /** `once` 큐 처리 */
    if (this.listenersOncer.length > 0) {
      const toCall = this.listenersOncer;
      this.listenersOncer = [];
      toCall.forEach((listener) => listener(event));
    }
  }

  pipe = (te: TypedEvent<T>): Disposable => {
    return this.on((e) => te.emit(e));
  }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://radlohead.gitbook.io/typescript-deep-dive/main-1/typed-event.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
