타입스크립트에서 클래스 다루기 - 2

this

자바스크립트에서 this가 어렵다고 느낀 이유는 this context가 다이나믹하게 바뀌기 때문이다. 예를 들어 다음 코드를 보자

// javascript
class Person {
  name = 'James'
  logName() {
    console.log(this.name)
  }
}

const p = new Person()
p.logName() // James

const obj = {
  name: 'obj',
  sayName: p.logName,
}

obj.sayName() // obj

this context는 함수를 어떻게 호출하냐에 따라 결정된다. obj를 통해서 logName을 호출하면 this context는 클래스 인스턴스가 아닌 obj로 결정된다.
this context를 클래스 인스턴스로 고정시키는 방법은 arrow function을 사용하는 것이다.

class Person {
  name = 'James'
  logName = () => {
    console.log(this.name)
  }
}

const p = new Person()
p.logName() // James

const obj = {
  name: 'obj',
  sayName: p.logName,
}

obj.sayName() // James

대신 이 방식에는 몇 가지 trade-offs가 있다.

this parameter

arrow function을 사용하는 대신 타입스크립트에서는 this context를 명시적으로 설정하여 컴파일 단계에서 context를 타입체크할 수 있다.

class Person {
  name = 'James'
  logName(this: Person) {
    console.log(this.name)
  }
}

const obj = {
  name: 'obj',
  sayName: p.logName,
}

obj.sayName() // ❌ Compile error
// The 'this' context of type '{ name: string; sayName: (this: Person) => void; }' is not assignable to method's 'this' of type 'Person'.
// Property 'logName' is missing in type '{ name: string; sayName: (this: Person) => void; }' but required in type 'Person'

this context를 정하는 방법에서 arrow function은 런타임 행동이고 this parameter는 컴파일 타임 행동이다.

this type

this의 타입은 동적으로 결정된다. 왜냐하면 클래스를 상속하는데 사용할 수 있기 때문이다.

References