TypeScript - 생성자 type

이종호·2021년 8월 2일
0

TypeScript

목록 보기
5/7
post-thumbnail

이 글은 엘리님 강의를 공부하면서 만들었습니다.

과제: PageItemComponent를 동적으로 받을 수 있게 하라

현재 PageComponent에서 PageItemComponent를 class형태로 받아오는 것은,
굉장히 제한적으로 값을 받아올 수 밖에 없다는 단점이 있다

만약 DartPageItempComponent, AnimationPageItemComponent등이 존재한다면 어떻게 구현할 것인가?

나는 이를 공통의 Interface를 구현하는 구현체로 만들고
PageComponent는 이 구현체를 통해 생성장에서 해당 중간 객체를 만듬으로써 좀 더 동적인 동작이 가능하게 할 것이다.

엘리님이 DI라 언급하셨는데, 이걸 검색해보면 뭔가 힌트를 더 얻지 않을까?
https://blog.shovelman.dev/964
이 글을 보다 말았는데, 뭔가 데코레이터까진 구현하지 않더라도 구현할 수 있을 거 같아서 돌아갔다.

내가 혼자 생각해본 구현

// ...

interface PageItem extends Composable, Component {
  setOnCloseListener: (listener: OnCloseListener) => void;
}

class PageItemComponent extends BaseComponent<HTMLElement> implements PageItem {
  // ...
}

export class PageComponent extends BaseComponent<HTMLUListElement>  implements Composable{
  private pageItem: PageItem;
  constructor(type: string) {
    super('<ul class="page"></ul>');
    if(type === 'default'){
      this.pageItem = new PageItemComponent();
    } else {
      this.pageItem = new PageItemComponent();
    }
  }
  
  addChild(section: Component) {
    // const item = new PageItemComponent();
    this.pageItem.addChild(section);
    this.pageItem.attachTo(this.element, 'beforeend');
    this.pageItem.setOnCloseListener(() => {
      this.pageItem.removeFrom(this.element);
    })
  }
}
  • 일단, PageItemComponent를 감싸는 interface를 만들어 주었고
  • 구성요소는 기존에 것들을 차용해 꼭 필요한 기능들만 넣어주었다.
    (여기서 드는 의문은 과연 interface에서 변수를 넣을 때가 있을까? 였다., 당장은 setOnCloseListener가 있기 때문에 굳이 넣어줄 필요가 없어 보여서 뺐다.)

실제 정답

// ...

// PageItem과 이름만 다르고 동일해서 기분이 좋았다!!
interface SectionContainer extends Composable, Component {
  setOnCloseListener: (listener: OnCloseListener) => void;
}

// 생성자 type은 처음 보는데 흠.. 너무 신기하고 자주 보면서 익숙해져가고 언제쓰이는지 이해해봐야겠다.
type SectionContainerConstructor = {
  new (): SectionContainer;
}

export class PageItemComponent extends BaseComponent<HTMLElement> implements SectionContainer {
  // ... 내용은 동일!
}

export class PageComponent extends BaseComponent<HTMLUListElement>  implements Composable{
  constructor(private pageItemConstructor: SectionContainerConstructor) { //  아직 이 문법이 익숙하지 않은데 빨리 습득해야겠다.
    super('<ul class="page"></ul>');
  }
  
  addChild(section: Component) {
    const item = new this.pageItemConstructor(); // 음..!
    item.addChild(section);
    item.attachTo(this.element, 'beforeend');
    item.setOnCloseListener(() => {
      item.removeFrom(this.element);
    })
  }
}
  • 생성자 type을 지정할 수 있다는게 놀라웠다.
  • 왜 그냥 SectionContainer를 쓰지 않을까 고쳐보았더니, interface자체적으로 생성자 함수를 구현하는 순간, 이미 PageItemComponent에서 SectionContainer를 구현했기 때문에, 충돌이 일어나기 때문에 생성자 type을 따로 만들 수 밖에 없다
    (내 풀이가 맞는지 모르겠다..)
profile
코딩은 해봐야 아는 것

0개의 댓글