npm은 자바스크립트 라이브러리 저장소(npm 레지스트리)와, 프로젝트가 의존하고 있는 라이브러리들의 버전을 지정하는 방법(package.json)을 제공한다.
✔️ npm의 3가지 종류의 의존성
dependencies
현재 프로젝트를 실행하는 데 필수적인 라이브러리들이 포함
devDependencies
현재 프로젝트를 개발하고 테스트하는 데 사용되지만, 런타임에는 필요 없는 라이브러리들이 포함
peerDependencies
런타임에 필요하긴 하지만, 의존성을 직접 관리하지 않는 라이브러리들이 포함
타입스크립트와 관련된 라이브러리는 일반적으로 devDependencies에 속한다
✔️ 모든 TS 프로젝트에서 공통적으로 고려해야 할 의존성 두 가지
타입스크립트 자체 의존성 고려하기
타입스크립트를 시스템 레벨로 설치하기보다는 devDependencies에 넣는 것이 좋다. npm install을 실행할 때 팀원들 모두 항상 정확한 버전의 타입스크립트를 설치 할 수 있다.
타입 의존성(@types) 고려하기
@types 라이브러리는 타입 정보만 포함하고 있으며 구현체는 포함하지 않는다. 원본 라이브러리 자체가 dependencies에 있더라도 @types 의존성은 devDependencies에 있어야 한다.
// 리액트
$ npm install react
$ npm install --save-dev @types/react
❗라이브러리의 버전, 타입 선언(@types)의 버전, 타입스크립트의 버전 이 셋 중 하나라도 맞지 않으면, 의존성과 상관없어 보이는 곳에서 엉뚱한 오류가 발생할 수 있다.
✔️ 타입스크립트에서 일반적으로 의존성을 사용하는 방식
$ npm install react
+ react@16.8.6
$ npm install --save-dev @types/react
+ @types/react@16.8.19
@types/react의 16.8.19는 타입 선언들이 리액트 16.8버전의 API를 나타낸다는 것을 의미한다.
👎 실제 라이브러리와 타입 정보의 버전이 별도로 관리되는 방식의 문제점
라이브러리를 업데이트했지만 실수로 타입 선언은 업데이트 하지 않은 경우
라이브러리 업데이트와 관련된 새로운 기능을 사용하려 할 때마다 타입 오류가 발생. 특히 하위 호환성이 깨지는 변경이 있었다면, 타입 체커를 통과하더라도 런타임에 오류가 발생할 수 있음.
✔️ 해결 방법 : 타입 선언도 업데이트하기
❓ 업데이트해야 할 타입 선언의 버전이 아직 준비되지 않은 경우라면?
👉 보강 기법을 활용하여 사용하려는 새 함수와 메서드의 타입 정보를 프로젝트 자체에 추가하거나 타입 선언의 업데이트를 직접 작성하기
라이브러리보다 타입 선언의 버전이 최신인 경우
라이브러리와 타입 선언의 버전 정보가 어긋날 수 있다.
✔️ 해결 방법 : 라이브러리와 타입 선언의 버전이 맞도록 라이브러리 버전을 올리거나 타입 선언의 버전을 내리기
프로젝트에서 사용하는 ts 버전보다 라이브러리에서 필요로 하는 ts 버전이 최신인 경우
lodash, react, ramda 같은 유명 js 라이브러리의 타입 정보를 더 정확하게 표현하기 위해서 ts에서 타입 시스템이 개선되고 버전이 올라가게 된다. 그러므로 이러한 라이브러리들의 최신 타입 정보를 얻기 위해서라면 당연히 ts의 최신 버전을 사용해야 한다.
✔️ 해결 방법 : 프로젝트의 ts 버전을 올리거나, 라이브러리 타입 선언의 버전을 원래대로 내리거나, declare module 선언으로 라이브러리의 타입 정보를 없애기
@types 의존성이 중복되는 경우
전역 네임스페이스에 있는 타입 선언 모듈이라면 대부분 문제발생
✔️ 해결 방법 : 서로 버전이 호환되게 하기
일부 라이브러리, 특히 ts로 작성된 라이브러리들은 자체적으로 타입 선언을 포함(번들링)하게 된다. 자체적인 타입 선언은 보통 package.json 의 "types" 필드에서 .d.ts 파일을 가리키도록 되어 있다.
공개 메서드에 등장한 어떤 형태의 타입이든 export 하자. 어차피 라이브러리 사용자가 추출할 수 있으므로, export 하기 쉽게 만드는 것이 좋다.