타입 선언과 @types
- 8.1 @types를 devDependencies에 넣기
- 8.2 타입 선언과 관련된 세 가지 버전 이해하기
- 8.3 공개 API에 등장하는 모든 타입을 익스포트하기
- 8.4 API 주석에 TSDoc 사용하기
- 8.5 콜백에서 this에 대한 타입 제공하기
- 8.6 미러 타입으로 의존성 관리하기
- 8.7 보강을 사용해서 타입 확장하기
자기 코드의 타입만 잘 쓰면 된다고 생각하기 쉬운데, 실제로는 서드파티 라이브러리의 타입 선언을 다루는 일이 엄청 많아.
@types 패키지는 타입 선언만 들어있으니까 런타임에 필요 없잖아. 그래서 **devDependencies**에 넣는 게 맞아. lodash는 dependencies에, @types/lodash는 devDependencies에. 배포할 때 @types가 같이 설치될 필요가 없으니까.
TS 프로젝트에서 타입 관련 버전이 세 가지 있는데, 이 셋이 꼬이면 온갖 이상한 에러가 나. 라이브러리 버전, @types 버전, 타입스크립트 버전 — 이 세 가지가 호환되어야 하거든. 라이브러리가 5.x인데 @types가 4.x면 새 API의 타입이 없고, TS 버전이 올라가면서 더 엄격해져서 이전엔 통과하던 타입이 에러나기도 해. 근본 원인은 라이브러리와 타입 선언이 별도 패키지로 관리되기 때문인데, 최근 트렌드는 라이브러리가 자체적으로 타입을 번들링하는 방향으로 가고 있어.
라이브러리를 만든다면 공개 API에서 사용되는 모든 타입을 익스포트해야 해. 타입을 숨겨봐야 사용자가 Parameters<typeof fn>[0] 같은 우회를 하게 되거든. 숨기는 의미가 없어.
/** */ 형태의 TSDoc 주석을 달면 편집기가 hover 시 보여줘. @param, @returns, @example 태그로 구조화된 문서를 작성할 수 있고, TypeDoc 같은 도구와도 호환돼. 4장에서 "주석에 타입 정보를 쓰지 마라"고 했는데, TSDoc에는 의도, 제약, 예시를 쓰는 거야.
콜백 함수에서 this의 타입을 TS한테 알려줘야 할 때가 있는데, this: HTMLElement 같은 특별한 문법으로 선언할 수 있어. 컴파일 후에는 사라지고, 화살표 함수에서는 못 쓰니까 반드시 일반 function을 써야 해.
라이브러리를 만들 때 @types/node에 의존하고 싶지 않으면 미러 타입을 써. 필요한 구조만 직접 선언하는 건데, 구조적 타이핑 덕분에 실제 Buffer를 넘겨도 호환돼. 불필요한 @types 의존성을 피하고 결합도를 낮출 수 있지.
**보강(augmentation)**은 인터페이스의 선언 병합을 활용해서 기존 타입에 속성을 추가하는 거야. Express의 Request에 user 속성을 추가하거나, Window 객체에 전역 변수 타입을 추가할 때 쓰지. 몽키 패치보다 훨씬 안전한 방법인데, 전역에 영향을 미치니까 충돌 가능성은 고려해야 해.
정리
8장 읽고 기억할 거 세 가지:
- 라이브러리 버전,
@types버전, TS 버전 — 이 세 가지가 맞아야 한다. 타입 에러가 이상하게 나면 버전 호환부터 체크. - 공개 API의 모든 타입을 익스포트하라. 숨겨봐야 사용자가
ReturnType같은 유틸리티로 추출할 수 있다. - 보강(augmentation)으로 기존 타입을 안전하게 확장할 수 있다. 몽키 패치보다 보강이 낫고, TSDoc으로 문서화하면 금상첨화.