#49 콜백에서 this에 대한 타입 제공하기

2023. 4. 23.·🎨 프론트엔드 공부/JS & TS

이펙티브 타입스크립트 (댄 밴더캄 지음) 를 읽고 정리

📍요약

✅콜백에서 this를 사용해야 한다면, this 바인딩을 확인해야 한다. 확인하려면 2가지 방법이 있다.

- 생성자에서..

- 화살표 함수를  사용..

 

📍JavaScript this 복습

C class를 만들고

logSquares 메서드를 정의한다

 

C의 인스턴스 c를 정의하고 메서드를 실행 => 정상

(this = c)

 

c의 메서드를 새로운 변수에 저장하고 그것을 호출 => 에러

(this = undefined)

 

call 메서드를 활용해 this에 c 바인딩 => 정상

class C {
  vals = [1, 2, 3];
  logSquares() {
    for (const val of this.vals) {
      console.log(val * val);
    }
  }
}

const c = new C();
c.logSquares(); // this = c 바인딩
// 1
// 4
// 9

// 메서드를 새로운 변수에 할당하면?
const method = c.logSquares; // this = undefined
method();
console.log(this); // undefined
// vals를 읽을 수 없음

// this 바인딩 제어하기
const method2 = c.logSquares;
method2.call(c); // this = c 바인딩
// 1
// 4
// 9

 

📍Class에서 this 바인딩 문제 해결하기

ResetButton 클래스에서 onClick 메서드를 호출하면 this가 정의되지 않아 에러가 발생

declare function makeButton(props: {text: string, onClick: () => void }): void;

class ResetButton {
  render() {
    return makeButton({text: 'Reset', onClick: this.onClick});
  }
  // onClick 메서드를 바로 호출하면 this 바인딩 문제로 에러
  onClick() {
    alert(`Reset ${this}`);
  }
}

 

✅해결방법 1

생성자에서 메서드에 this를 바인딩

 

onClick 메서드에 this가 바인딩되어 해당 인스턴스에 onClick 메서드가 새로 생성됨

인스턴스에서 생성된 onClick 메서드는 ResetButton 프로토타입의 onClick 메서드보다 앞에 놓이므로 (프로토타입 체인)

render 메서드의 this.onClick은 바인딩된 메서드를 참조

declare function makeButton(props: {text: string, onClick: () => void }): void;
class ResetButton {
  constructor() {
    this.onClick = this.onClick.bind(this); // 인스턴스가 만들어지면 onClick 메서드에 바로 this가 바인딩됨
  }
  render() {
    return makeButton({text: 'Reset', onClick: this.onClick});
  }
  onClick() {
    alert(`Reset ${this}`);
  }
}

 

✅해결방법 2

더 간단하게 해결하려면 화살표 함수를 사용하면 된다

 

ResetButton의 인스턴스가 생성될 때마다 제대로 바인딩된 this를 가지는 새 함수를 생성

declare function makeButton(props: {text: string, onClick: () => void }): void;
class ResetButton {
  render() {
    return makeButton({text: 'Reset', onClick: this.onClick});
  }
  onClick = () => {
    alert(`Reset ${this}`);  // "this" 가 항상 인스턴스를 참조
  }
}

 

📍예시 2

✅생성자에서 this를 추가하거나, 화살표 함수를 사용하여 this 바인딩 에러를 방지하자!

function addKeyListener(
  el: HTMLElement,
  // 콜백 함수 fn의 매개변수에 this를 추가하면 this 바인딩을 체크하므로 에러를 잡아낼 수 있음
  fn: (this: HTMLElement, e: KeyboardEvent) => void
) {
  el.addEventListener('keydown', e => {
    fn(e);
 // ~~~~~ The 'this' context of type 'void' is not assignable
 //       to method's 'this' of type 'HTMLElement'
  });
}
class Foo {
  registerHandler(el: HTMLElement) {
    // 일반 함수에서는 에러 잡아낼 수 없음!
    addKeyListener(el, function (e) {
      this.innerHTML;
    });

    // 화살표 함수는 에러를 잡아낼 수 있음!
    addKeyListener(el, e => { 
      this.innerHTML;
        // ~~~~~~~~~ Property 'innerHTML' does not exist on type 'Foo'
    });
  }
}
'🎨 프론트엔드 공부/JS & TS' 카테고리의 다른 글
  • #51 의존성 분리를 위해 미러 타입 사용하기
  • #50 오버로딩 타입보다는 조건부 타입을 사용하기
  • #48 API 주석에 TSDoc 사용하기
  • #47 Public API에 등장하는 모든 타입을 export하기
지식물원
지식물원
지식이 자라는 식물원!
  • 지식물원
    지식물원
    지식물원
  • 전체
    오늘
    어제
    • 분류 전체보기 (510)
      • 🎨 프론트엔드 공부 (247)
        • JS & TS (86)
        • HTML & CSS (22)
        • React & Next (49)
        • Vue & Nuxt (22)
        • 기타 (68)
      • 🤓 기술 학습 & 공부 기록 (116)
        • Node.js (0)
        • Python (37)
        • 백엔드 (0)
        • 딥러닝 (1)
        • 컴퓨터 일반 (72)
        • 개발 인프라 (6)
      • 👨‍💻 프로젝트 경험 (6)
        • Work (0)
        • Toy (6)
      • ⚙️ 개발 팁 & 노하우 (21)
        • 프론트엔드 (6)
        • 기타 (15)
      • ☕️ 커리어 & 인터뷰 준비 (88)
        • 코딩 테스트 (88)
      • 📰 기술 트렌드 & 생각 정리 (4)
      • 📚 기타 (25)
        • 마케팅 (15)
        • 비개발서적 (10)
  • 블로그 메뉴

    • 태그
  • 링크

  • 공지사항

    • 모바일 접속 시 코드 하이라이팅 깨질 때
  • 인기 글

  • hELLO· Designed By정상우.v4.10.3
지식물원
#49 콜백에서 this에 대한 타입 제공하기
상단으로

티스토리툴바