Chapter 5

불안전한 any 타입

  • 5.1 any 타입은 가능한 한 좁은 범위에서만 사용하기
  • 5.2 any를 구체적으로 변형해서 사용하기
  • 5.3 unknown은 any 대신 쓸 수 있는 안전한 타입
  • 5.4 몽키 패치보다는 안전한 타입 접근
  • 5.5 타입 커버리지를 추적하여 타입 안전성 유지하기

1장에서 "any를 지양하라"고 했지만, 현실에서 any를 완전히 안 쓸 수는 없잖아. 레거시 코드, 서드파티 라이브러리, 복잡한 타입 표현이 불가능한 경우가 있으니까. 5장은 any를 써야 할 때 어떻게 피해를 최소화하느냐에 대한 이야기야.

핵심은 any의 영향 범위를 최소화하라는 거야. 변수를 any로 선언하면 그 이후 모든 곳에서 타입 체크가 꺼지지만, as any를 호출 시점에만 쓰면 나머지 코드의 타입 안전성은 유지돼. any는 전염되거든. 함수의 반환 타입이 any가 되면, 그 함수를 호출하는 코드에서도 any가 퍼져. 그래서 함수 반환 타입을 명시하면 any가 함수 밖으로 빠져나가는 걸 막을 수 있어.

순수한 any 대신 좀 더 구체적인 형태를 쓰는 것도 방법이야. **any[]**는 "뭔진 모르겠지만 배열이다", **{[key: string]: any}**는 "뭔진 모르겠지만 객체다", **(...args: any[]) => any**는 "뭔진 모르겠지만 함수다"라는 뜻이거든. any 대신 any[]를 쓰면 .lengthnumber로 추론되고, 배열이 아닌 값이 들어오면 에러를 잡을 수 있어.

**unknown**은 any의 타입 안전한 대안이야. 둘 다 모든 값을 받을 수 있는데, 차이는 사용할 때 발생해. any는 아무 연산이나 할 수 있지만, unknown먼저 타입을 좁혀야 사용할 수 있거든. "이 값의 타입을 모르겠다"를 표현하면서도 타입 체크를 유지하는 거지. 외부에서 들어오는 데이터(API 응답, JSON 파싱 결과)에 특히 적합해.

JS에서 흔한 몽키 패치(document.monkey = 'Tamarin')는 TS에서 에러가 나는데, as any로 우회하는 건 나쁜 방법이야. **보강(augmentation)**을 써서 인터페이스의 선언 병합으로 기존 타입에 속성을 추가하면 타입 안전하게 확장할 수 있어. 또는 WeakMap을 써서 객체에 연관 데이터를 저장하는 방법도 있지.

서드파티 라이브러리의 타입 선언에 any가 숨어있을 수도 있어. @types 패키지의 함수가 any를 반환하면 내 코드도 오염되거든. type-coverage 같은 도구로 코드베이스에서 any 비율을 추적하고, 서드파티에서 any가 반환되면 내 코드에서 타입을 재선언해서 차단해야 해.


정리

5장 읽고 기억할 거 세 가지:

  1. any는 전염된다. 좁은 스코프에 가두고, 함수 경계에서 차단하라.
  2. unknownany의 안전한 대안이다. 타입을 모를 때 any 대신 unknown을 쓰고, 타입 좁히기로 안전하게 사용하라.
  3. 타입 커버리지를 추적하라. 서드파티 라이브러리에서 any가 스며들 수 있으니, 정기적으로 모니터링해야 한다.