타입선언과 @types
npm은 자바스크립스에서 필수적입니다.
자바스크립트 라이브러리 저장소(npm 레지스토리)와 프로젝트가 의존하고 있는 라이브러리들의 버전을 지정하는 방법(package.json)을 제공합니다.
npm은 세 가지 종류의 의존성을 구분해서 관리합니다
1. Dependencies
2.devDependencies
3.peerDependencies
타입스크립트와 관련된 라이브러리들은 일반적으로 devDependencies에 속하게 됩니다.
모든 타입스크립트 프로젝트에서 공통적으로 고려해야 할 의존성 2가지
2.타입의존성을 고려해야 합니다.
의존성 사용시 타입스크립트를 사용할 때 3가지 사항을 추가로 고려해야합니다.
이 세가지 버전 중 하나라도 맞지 않으면, 의존성과 상관없어 보이는 곳에서 엉뚱한 오류가 발생할 수 있습니다.
해결법:
- 보강 기법을 통한 타입 정보를 프로젝트 자체에 추가
- 타입 선언의 업데이트를 직접 작성하고 공개하여 커뮤니티에 기여
해결법:
타입 선언의 버전이 맞도록 라이브러리 버전을 올리거나 타입 선언의 버전을 내리는 방법으로 해결
3.프로젝트에서 사용하는 타입스크립트 버전보다 라이브러리에서 필요로 하는 타입스크립트 버전이 최신인 경우
프로젝트의 버전을 높이거나 라이브러리 타입 선언의 버전을 원래대로 내림
4.@types 의존성이 중복될 수 있습니다.
일반적으로 ts라이브러리들은 자체적으로 타입 선언을 포함(번들링)하게 된다. → index.d.ts 파일을 가리키게함 그러나 이러한 번들링 방식은 부수적인 4가지 문제점을 가짐
JS로 작성된 라이브러리는 타입 선언을 DefinitelyTyped에 공개하여 커뮤니티에서 관리하고 유지보수하도록 맡기는 것이 좋다!
공개 메서드에 등장한 어떤형태의 타입이든 익스포트합시다. 어차피 라이브러리 사용자가 추출할 수 있으므로 , 익스포트하기 쉽게 만드는 것이 좋습니다.
JSDoc/TSDoc으로 사용시 툴팁으로 표시를 해주기 때문입니다.
또한 TSDoc은 마크다운형식으로 꾸밀 수 있습니다.
this는 다이나믹 스코프이기 때문에 다이나믹 스코프의 값은 '정의된'방식이 아니라 '호출된' 방식에 따라 달라집니다.
자바스크립트에서는 call을 사용하면 명시적으로 this를 바인딩하여 문제를 해결할 수 있습니다.
콜백함수에서 this 값을 사용해야 한다면 this는 api의 일부가 되는 것이기 때문에 반드시 타입선언에 포함해야합니다.
오버로딩으로 타입에 따른 함수들을 다 정의하기보다, 아래와 같이 조건부 타입을 이용하면 유니온 타입 또한 조건부 타입의 유니온으로 분리되어 잘 작동합니다.
function double<T extends string | number>(x: T): T extends string ? string : number;
미러타입이란?
라이브러리에서 필요한 선언부만 추출하여 작성중인 라이브러리에 넣는 것
만약 작성 중인 라이브러리가 의존하는 라이브러리의 구현과 무관하게 타입에만 의존한다면, 필요한 선언부만 추출하여 작성 중인 라이브러리에 넣는것을 고려해 보는 것도 좋다.
공개한 라이브러리를 사용하는 자바스크립트 사용자가 @types 의존성을 가지지 않게 해야 합니다. 그리고 웹 개발자가 NodeJS 관련된 의존성을 가지지 않게 해야 합니다.
→ 따라서 이러한 경우 타입을 devDependencies로 추가하기보다, 각자가 필요한 모듈만 사용할 수 있도록 구조적 타이핑을 적용하면 좋다. 그러나 타입의 대부분을 추출해야하는 경우는 명시적으로 @types 의존성을 추가하는게 낫다.
DefinitelyTyped의 타입 선언을 위한 도구로 dtslint를 소개하며 이를 사용하는 것을 추천합니다.
dtslint는 특별한 형태의 주석을 통해 동작합니다.
dtslint는 할당 가능성을 체크하는 대신 각 심벌의 타입을 추출하여 글자 자체가 같은지 비교한다. 그러나 이러한 방식에도 단점이 있는데, number|string과 string|number는 같은 타입이지만 글자 자체로 보면 다르기 때문에 다른 타입으로 인식된다.