Item 43 몽키 패치보다는 안전한 타입을 사용하기

JavaScript의 특징

자바스크립트의 가장 유명한 특징 중 하나는, 객체와 클래스에 임의의 속성을 추가할 수 있을 만큼 유연하다는 것이다.

객체에 속성을 추가할 수 있는 기능은 종종 웹 페이지에서 window, document에 값을 할당해 전역 변수를 만드는 데 사용된다.

하지만 객체에 임의의 속성을 추가하는 것은 일반적으로 좋은 설계는 아니다.

TypeScript에서의 몽키 패치

타입스크립트까지 더하면 문제가 발생하는데, 임의로 추가한 속성에 대해 타입 체커가 알 수 없다는 것이다.

해결 방법으로 any 단언문(as any)을 사용하는 것이 있지만, 타입 안전성을 상실하고, 언어 서비스를 사용할 수 없게 된다는 치명적인 단점이 있다.

이를 해결하기 위한 두 가지 차선책이 있다.

1. 보강(augmentation) 사용하기

방법 중 하나는 interface의 특수 기능 중 하나인 보강(augmentation)을 사용하는 것이다.

Item 13 타입과 인터페이스의 차이점 알기

interface Document {
  /** 몽키 패치의 속(genus) 또는 종(species) */
  monkey: string
}

document.monkey = 'Tamarin' // 정상

보강을 사용한 방법이 any보다 나은 점은 다음과 같다:

  • 타입이 더 안전하다. 타입 체커가 오타, 잘못된 타입의 할당을 오류로 표시한다.

  • 속성에 주석을 붙일 수 있다. (Item 48)

  • 속성에 자동완성을 사용할 수 있다.

  • 몽키 패치가 어떤 부분에 적용되었는지 정확한 기록이 남는다.

참고로 모듈에서(TS 파일이 import/export를 사용하는 경우) 제대로 동작하게 하려면 global 선언을 해야 한다.

export {}
declare global {
  interface Document {
    /** 몽키 패치의 속(genus) 또는 종(species) */
    monkey: string
  }
}

document.monkey = 'Tamarin' // 정상

2. 더 구체적인 타입 단언문 사용하기

interface MonkeyDocument extends Document {
  /** 몽키 패치의 속(genus) 또는 종(species) */
  monkey: string
}

(document as MonkeyDocument).monkey = 'Macaque'

MonkeyDocumentDocument를 확장하므로(Item 9 타입 단언보다는 타입 선언을 사용하기) 타입 단언문은 정상이며 할당문의 타입은 안전하다.

또한 Document 타입을 건드리지 않고 별도로 확장하는 새로운 타입을 도입했기 때문에 모듈 영역 문제도 해결할 수 있다.

따라서 몽키 패치된 속성을 참조하는 경우에만 단언문을 사용하거나 새로운 변수를 도입하면 된다.

Summary

  • 전역 변수/DOM에 데이터를 저장하지 말고, 데이터를 분리하여 사용해야 한다.

  • 내장 타입에 데이터를 저장해야 하는 경우, 안전한 타입 접근법 중 하나(1. 보강, 2. 사용자 정의 인터페이스로 단언)를 사용해야 한다.

  • 보강의 모듈 영역 문제를 이해해야 한다.

Last updated