개발새발

ThisType 본문

Typescript

ThisType

비숑주인 2025. 4. 12. 14:09

타입스크립트를 사용할 때, 객체 리터럴 내 메서드에서 this의 타입을 자동으로 추론하고 싶을 때가 있다. 하지만 기본적으로 타입스크립트는 객체 리터럴에서 this의 타입을 추론하지 못하기 때문에 this.money, this.name 등의 코드에서 타입 오류가 발생할 수 있다.

 

이 문제를 해결하기 위한 강력한 유틸리티 타입이 바로 ThisType<T> 이다.

const obj = {
  data: {
    money: 0,
  },
  methods: {
    addMoney(amount: number) {
      this.money += amount; // ❌ 에러: Property 'money' does not exist on type ...
    },
  },
};

 

위 코드는 실행 상 문제는 없지만 타입스크립트는 this의 타입을 알지 못해 오류를 발생시킨다. 

 

해결 방법 1: 메서드에 직접 this 타이핑

type Data = { money: number };
type Methods = {
  addMoney(this: Data & Methods, amount: number): void;
};

const obj = {
  data: { money: 0 },
  methods: {
    addMoney(amount) {
      this.money += amount;
    },
  },
} satisfies {
  data: Data;
  methods: Methods;
};

 

이 방법은 명확하지만 모든 메서드마다 this: Data & Methods를 일일이 작성해야 한다는 단점이 있다.

 

해결 방법 2: ThisType<T> 활용

type Data = { money: number };
type Methods = {
  addMoney(amount: number): void;
  useMoney(amount: number): void;
};

type Obj = {
  data: Data;
  methods: Methods & ThisType<Data & Methods>;
};

const obj: Obj = {
  data: {
    money: 0,
  },
  methods: {
    addMoney(amount) {
      this.money += amount;
    },
    useMoney(amount) {
      this.money -= amount;
    },
  },
};

 

장점

  • methods 내부의 메서드들은 this를 자동으로 Data & Methods 타입으로 추론한다.
  • this.data.money처럼 중첩 접근할 필요 없이 this.money로 바로 접근할 수 있다.
  • 메서드가 많아질수록 생산성이 압도적으로 향상된다.

 

ThisType<T>는 어떻게 정의되어 있을까?

타입스크립트의 기본 타입 정의 파일 lib.es5.d.ts에는 이렇게 선언되어 있다. 

interface ThisType<T> {}

 

비어 있는 인터페이스처럼 보이지만, 타입스크립트 내부에서 특별하게 처리되는 타입(intrinsic) 이다. 타입 시스템이 이 타입을 해석할 때 this를 T로 간주하도록 해준다.

 

주의할 점

  • ThisType<T>는 객체 리터럴 내부에서만 동작한다. 클래스를 비롯한 다른 컨텍스트에서는 효과가 없다.
  • ThisType<T>는 런타임에는 아무 영향이 없으며, 오직 타입 수준에서만 작동한다.
  • methods: Methods & ThisType<...>처럼 반드시 인터섹션 형태로 함께 제공되어야 한다.

 

보너스: 함께 정의된 intrinsic 문자열 유틸리티 타입

같은 위치에는 다음과 같은 문자열 유틸리티 타입도 정의되어 있다:

type Uppercase<S extends string> = intrinsic;
type Lowercase<S extends string> = intrinsic;
type Capitalize<S extends string> = intrinsic;
type Uncapitalize<S extends string> = intrinsic;
 

 

이 타입들 역시 내부 구현은 볼 수 없지만, 타입 수준에서 매우 유용하게 사용된다.

type U = Uppercase<'hello'>;      // 'HELLO'
type C = Capitalize<'world'>;     // 'World'

 

 

유틸리티 타입 설명
ThisType<T> 객체 리터럴 내 메서드에서 this를 T로 추론하게 해주는 타입

ThisType을 활용하면, 복잡한 객체 모델에서도 this 오류 없이 타입 안정성을 유지할 수 있다. 특히 Vue 컴포넌트, mixin 스타일 객체 구성, composition 패턴을 사용할 때 매우 유용하다.

 

'Typescript' 카테고리의 다른 글

map 만들기  (0) 2025.04.30
forEach 만들기  (0) 2025.04.29
Parameters, Constructorparameters, ReturnType, InstanceType  (0) 2025.04.12
Exclude, Extract, Omit, NonNullable  (0) 2025.04.12
Partial, Required, Readonly, Pick, Record  (0) 2025.04.12