item1 타입스크립트와 자바스크립트의 관계 이해하기
- 타입스크립트는 자바스크립트의 상위집합입니다. 다시 말해서, 모든 자바스크립트 프로그램은 이미 타입스크립트 프로그램입니다. 반대로, 타입스크립트는 별도의 문법을 가지고 있기 때문에 일반적으로는 유효한 자바스크립트 프로그램이 아닙니다.
- 타입스크립트는 자바스크립트 런타임 동작을 모델링하는 타입 시스템을 가지고 있기 때문에 런타임 오류를 발생시키는 코드를 찾아내려고 합니다. 그러나 모든 오류를 찾아내리라 기대하면 안 됩니다. 타입 체커를 통과하면서도 런타임 오류를 발생시키는 코드는 충분히 존재할 수 있습니다.
const names = ['Alice', 'Bob']
console.log(names[2].toUpperCase())
export default {}
- 타입스크립트 타입 시스템은 전반적으로 자바스크립트 동작을 모델링합니다. 그러나 잘못된 매개변수 개수로 함수를 호출하는 경우처럼, 자바스크립트에서는 허용되지만 타입스크립트에서는 문제가 되는 경우도 있습니다. 이러한 문법의 엄격함은 온전히 취향의 차이이며 우열을 가릴 수 없는 문제입니다.
const a = null + 7
const b = [] + 12
alert('Hello', 'TypeScript')
item2 타입스크립트 설정 이해하기
- 타입스크립트 컴파일러는 언어의 핵심 요소에 영향을 미치는 몇 가지 설정을 포함하고 있습니다.
- 타입스크립트 설정은 커맨드 라인을 이용하기보다는 tsconfig.json을 사용하는 것이 좋습니다.
- 자바스크립트 프로젝트를 타입스크립트로 전환하는 게 아니라면 noImplicitAny를 설정하는 것이 좋습니다.
- noImplictAny : 변수들이 미리 정의된 타입을 가져야 하는 지 여부
- “undefined는 객체가 아닙니다” 같은 런타임 오류를 방지하기 위해 strictNullChecks를 설정하는 것이 좋습니다.
- 타입스크립트에서 엄격한 체크를 하고 싶다면 strict 설정을 고려해야 합니다.
item3 코드 생성과 타입이 관계없음을 이해하기
- 코드 생성은 타입 시스템과 무관합니다. 타입스크립트 타입은 런타임 동작이나 성능에 영향을 주지 않습니다.
- 타입스크립트 컴파일러의 두가지 역할 (둘은 독립적 작동함)
- 최신 타입스크립트/자바스크립트를 브라우저에서 동작할 수 있도록 구버전의 자바스크립트로 트랜스파일 합니다.
- 코드의 타입 오류를 체크합니다.
- 타입 오류가 존재하더라도 코드 생성(컴파일)은 가능합니다.
- 타입스크립트 타입은 런타임에 사용할 수 없습니다. 런타임에 타입을 지정하려면, 타입 정보 유지를 위한 별도의 방법이 필요합니다. 일반적으로는 태그된 유니온과 속성 체크 방법을 사용합니다. 또는 클래스 같이 타입스크립트 타입과 런타임 값, 둘 다 제공하는 방법이 있습니다.
item4 구조적 타이핑에 익숙해지기
- 자바스크립트가 덕 타이핑(duck typing)기반이고 타입스크립트가 이를 모델링하기 위해 구조적 타이핑을 사용함을 이해해야 합니다. 어떤 인터페이스에 할당 가능한 값이라면 타입 선언에 명시적으로 나열된 속성들을 가지고 있을 겁니다. 타입은 ‘봉인’되어 있지 않습니다.
- 덕타이핑 : 객체가 어떤 타입에 부합하는 변수와 메서드를 가질 경우 객체를 해당 타입에 속하는 것으로 간주하는 방식
- 클래스 역시 구조적 타이핑 규칙을 따른다는 것을 명심해야 합니다. 클래스의 인스턴스가 예상과 다를 수 있습니다.
- 구조적 타이핑을 사용하면 유닛 테스팅을 손쉽게 할 수 있습니다.
item5 any 타입 지양하기
- any 타입을 사용하면 타입 체커와 타입스크립트 언어 서비스를 무력화시켜 버립니다. any 타입은 진짜 문제점을 감추며, 개발 경험을 나쁘게 하고, 타입 시스템의 신뢰도를 떨어뜨립니다. 최대한 사용을 피하도록 합시다.
item6 편집기를 사용하여 타입 시스템 파악하기
- 편집기에서 타입스크립트 언어 서비스를 적극 활용해야 합니다.
- 편집기를 사용하면 어떻게 타입 시스템이 동작하는지, 그리고 타입스크립트가 어떻게 타입을 추론하는지 개념을 잡을 수 있습니다.
- 타입스크립트가 동작을 어떻게 모델링하는지 알기 위해 타입 선언 파일을 찾아보는 방법을 터득해야 합니다.
item7 타입이 값들의 집합이라고 생각하기
- 타입을 값의 집합으로 생각하면 이해하기 편합니다(타입의 ‘범위’). 이 집합은 유한(boolean 또는 리터럴 타입)하거나 무한(number 또는 string)합니다.
- 타입스크립트 타입은 엄격한 상속 관계가 아니라 겹쳐지는 집합(벤 다이어그램)으로 표현됩니다. 두 타입은 서로 서브타입이 아니면서도 겹쳐질 수 있습니다.
- 한 객체의 추가적인 속성이 타입 선언에 언급되지 않더라도 그 타입에 속할 수 있습니다.
- 타입 연산은 집합의 범위에 적용됩니다. A와 B의 인터섹션은 A의 범위와 B의 범위의 인터섹션입니다. 객체 타입에서는 A & B인 값이 A와 B의 속성을 모두 가짐을 의미합니다.
- ‘A는 B를 상속’, ‘A는 B에 할당 가능’, ‘A는 B의 서브타입’은 ‘A는 B의 부분 집합’과 같은 의미입니다.
item8 타입 공간과 값 공간의 심벌 구분하기
- 타입스크립트 코드를 읽을 때 타입인지 값인지 구분하는 방법을 터득해야 합니다. 타입스크립트 플레이그라운드를 활용해 개념을 잡는 것이 좋습니다.
- 모든 값은 타입을 가지지만, 타입은 값을 가지지 않습니다. type과 interface 같은 키워드는 타입 공간에만 존재합니다.
- class나 enum 같은 키워드는 타입과 값 두 가지로 사용될 수 있습니다.
- “foo”는 문자열 리터럴이거나, 문자열 리터럴 타입일 수 있습니다. 차이점을 알고 구별하는 방법을 터득해야 합니다.
- typeof, this 그리고 많은 다른 연산자들과 키워드들은 타입 공간과 값 공간에서 다른 목적으로 사용될 수 있습니다.
item9 타입 단언보다는 타입 선언을 사용하기
- 타입 단언(as Type)보다 타입 선언(: Type)을 사용해야 합니다.
- 화살표 함수의 반환 타입을 명시하는 방법을 터득해야 합니다.
- 타입스크립트보다 타입 정보를 더 잘 알고 있는 상황에서는 타입 단언문과 null 아님 단언문을 사용하면 됩니다.
item10 객체 래퍼 타입 피하기
- 기본형 값에 메서드를 제공하기 위해 객체 래퍼 타입이 어떻게 쓰이는지 이해해야 합니다. 직접 사용하거나 인스턴스를 생성하는 것은 피해야 합니다.
- 타입스크립트 객체 래퍼 타입은 지양하고, 대신 기본형 타입을 사용해야 합니다. String 대신 string, Number 대신 number, Boolean 대신 boolean, Symbol 대신 symbol, BigInt 대신 bigint를 사용해야 합니다.
item11 잉여 속성 체크의 한계 인지하기
- 객체 리터럴을 변수에 할당하거나 함수에 매개변수로 전달할 때 잉여 속성 체크가 수행됩니다.
- 잉여 속성 체크는 오류를 찾는 효과적인 방법이지만, 타입스크립트 타입 체커가 수행하는 일반적인 구조적 할당 가능성 체크와 역할이 다릅니다. 할당의 개념을 정확히 알아야 잉여 속성 체크와 일반적인 구조적 할당 가능성 체크를 구분할 수 있습니다.
- 잉여 속성 체크에는 한계가 있습니다. 임시 변수를 도입하면 잉여 속성 쳌르르 건너뛸 수 있다는 점을 기억해야 합니다.
item12 함수 표현식에 타입 적용하기
- 매개변수나 반환 값에 타입을 명시하기보다는 함수 표현식 전체에 타입 구문을 적용하는 것이 좋습니다.
- 만약 같은 타입 시그니처를 반복적으로 작성한 코드가 있다면 함수 타입을 분리해내거나 이미 존재하는 타입을 찾아보도록 합니다. 라이브러리를 직접 만든다면 공통 콜백에 타입을 제공해야 합니다.
- 다른 함수의 시그니처를 참조하려면 typeof fn을 사용하면 됩니다.
item13 타입과 인터페이스의 차이점 알기
- 타입과 인터페이스의 차이점과 비슷한 점을 이해해야 합니다.
- 한 타입을 type과 interface 두 가지 문법을 사용해서 작성하는 방법을 터득해야 합니다.
- 프로젝트에서 어떤 문법을 사용할지 결정 할 대 한 가지 일관된 스타일을 확립하고, 보강 기법이 필요한지 고려해야 합니다.
item14 타입 연산과 제네릭 사용으로 반복 줄이기
- DRY(Don’t Repeat Yourself) 원칙을 타입에도 최대한 적용해야 합니다.
- 타입에 이름을 붙여서 반복을 피해야 합니다. extends를 사용해서 인터페이스 필드의 반복을 피해야 합니다.
- 타입들 간의 매핑을 위해 타입스크립트가 제공한 도구들을 공부하면 좋습니다. 여기에는 keyof, typeof, 인덱싱, 매핑된 타입들이 포함됩니다.
- 제네릭 타입은 타입을 위한 함수와 같습니다. 타입을 반복하는 대신 제너릭 타입을 사용하여 타입들 간에 매핑을 하는 것이 좋습니다. 제너릭 타입을 제한하려면 extends를 사용하면 됩니다.
- 표준 라이브러리에 정의된 Pick, Partial, ReturnType과 같은 제너릭 타입에 익숙해져야 합니다.
item15 동적 데이터에 인덱스 시그니처 사용하기
- 런타임 대까지 객체의 속성을 알 수 없을 경우에만(예를 들어 csv파일에서 로드하는 경우) 인덱스 시그니처를 사용하도록 합니다.
- 안전한 접근을 위해 인덱스 시그니처의 값 타입에 undefined 를 추가하는 것을 고려해야 합니다.
- 가능하다면 인터페이스, Record, 매핑된 타입 같은 인덱스 시그니처보다 정확한 타입을 사용하는 것이 좋습니다.
item16 number 인덱스 시그니처보다는 Array, 튜플, ArrayLike를 사용하기
- 배열은 객체이므로 키는 숫자가 아니라 문자열입니다. 인덱스 시그니처로 사요된 number 타입은 버그를 잡기 위한 순수 타입스크립트 코드입니다.
- 인덱스 시그니처에 number를 사용하기 보다 Array나 튜플, 또는 ArrayLike 타입을 사용하는 것이 좋습니다.
item17 변경 관련된 오류 방지를 위해 readonly 사용하기
- 만약 함수가 매개변수를 수정하지 않는다면 readonly로 선언하는 것이 좋습니다. readonly 매개변수는 인터페이스를 명확하게 하며, 매개변수가 변경되는 것을 방지합니다.
- readonly를 사용하면 변경하면서 발생하는 오류를 방지할 수 이쏙, 변경이 발생하는 코드도 쉽게 찾을 수 있습니다.
- const와 readonly의 차이를 이해해야 합니다.
- readonly는 얕게 동작한다는 것을 명심해야 합니다.
item18 매핑된 타입을 사용하여 값을 동기화하기
- 매핑된 타입을 사용해서 관련된 값과 타입을 동기화하도록 합니다.
- 인터페이스에 새로운 속성을 추가할 때, 선택을 강제하도록 매핑된 타입을 고려해야 합니다.
item19 추론 가능한 타입을 사용해 장황한 코드 방지하기
- 타입스크립트가 타입을 추론할 수 있다면 타입 구문을 작성하지 않는 게 좋습니다.
- 이상적인 경우 함수/메서드의 시그니처에는 타입 구문이 있지만, 함수 내의 지역 변수에는 타입 구문이 없습니다.
- 추론될 수 있는 경우라도 객체 리터럴과 함수 반환에는 타입 명시를 고려해야 합니다. 이는 내부 구현의 오류가 사용자 코드 위치에 나타나는 것을 방지해 줍니다.
item20 다른 타입에는 다른 변수 사용하기
- 변수의 값은 바뀔 수 있지만 타입은 일반적으로 바뀌지 않습니다.
- 혼란을 막기 위해 타입이 다른 값을 다룰 때에는 변수를 재사용하지 않습니다.
item21 타입 넓히기
- 타입스크립트가 넓히기를 통해 상수의 타입을 추론하는 법을 이해해야 합니다.
- 동작에 영향을 줄 수 방법인 const, 타입 구문, 문맥, as const에 익숙해져야 합니다.
item22 타입 좁히기
- 분기문 외에도 여러 종류의 제어 흐름을 살펴보며 타입스크립트가 타입을 좁히는 과정을 이해해야 합니다.
- 태그된/구별된 유니온과 사용자 정의 타입 가드를 사용하여 타입 좁히기 과정을 원활하게 만들 수 있습니다.
item23 한꺼번에 객체 생성하기
- 속성을 제각가 추가하지 말고 한꺼번에 객체로 만들어야 합니다. 안전한 타입으로 속성을 추가하려면 객체 전개({…a, …b})를 사용하면 됩니다.
- 객체에 조건부로 속성을 추가하는 방법을 익히도록 합니다.
item24 일관성 있는 별칭 사용하기
- 별칭은 타입스크립트가 타입을 좁히는 것을 방해합니다. 따라서 변수에 별칭을 사용할 때는 일관되게 사용해야 합니다.
- 비구조화 문법을 사용해서 일관된 이름을 사용하는 것이 좋습니다.
- 함수 호출이 객체 속성의 타입 정제를 무효화할 수 있다는 점을 주의해야 합니다. 속성보다 지역 변수를 사용하면 타입 정제를 믿을 수 있습니다.
item25 비동기 코드에는 콜백 대신 async 함수 사용하기
-
콜백보다는 프로미스를 사용하는 게 코드 작성과 타입 추론 면에서 유리합니다.
-
가능하면 프로미스를 생성하기보다는 async와 await를 사용하는 것이 좋습니다. 간결하고 직관적인 코드를 작성할 수 있고 모든 종류의 오류를 제거할 수 있습니다.
-
어떤 함수가 프로미스를 반환한다면 async로 선언하는 것이 좋습니다.
item26 타입 추론에 문맥이 어떻게 사용되는지 이해하기
- 타입 추론에서 문맥이 어떻게 쓰이는지 주의해서 살펴봐야 합니다.
- 변수를 뽑아서 별도로 선언했을 때 오류가 발생한다면 타입 선언을 추가해야 합니다.
- 변수가 정말로 상수라면 상수 단언(as const)을 사용해야 합니다. 그러나 상수 단언을 사용하면 정의한 곳이 아니라 사용한 곳에서 오류가 발생하므로 주의해야 합니다.
item27 함수형 기법과 라이브러리로 타입 흐름 유지하기
- 타입 흐름을 개선하고, 가독성을 높이고, 명시적인 타입 구문의 필요성을 줄이기 위해 직접 구현하기보다는 내장된 함수형 기법과 로대시 같은 유틸리티 라이브러리를 사용하는 것이 좋습니다.
item28 유효한 상태만 표현하는 타입을 지향하기
- 유효한 상태와 무효한 상태를 둘 다 표현하는 타입은 혼란을 초래하기 쉽고 오류를 유발하게 됩니다.
- 유효한 상태만 표현하는 타입을 지향해야 합니다. 코드가 길어지거나 표현하기 어렵지만 결국은 시간을 절약하고 고통을 줄일 수 있습니다.
item29 사용할 때는 너그럽게, 생성할 때는 엄격하게
- 보통 매개변수 타입은 반환 타입에 비해 범위가 넓은 경향이 있습니다. 선택적 속성과 유니온 타입은 반환 타입보다 매개변수 타입에 더 일반적입니다.
- 매개변수와 반환 타입의 재사용을 위해서 기본 형태(반환 타입)와 느슨한 형태(매개변수 타입)를 도입하는 것이 좋습니다.
item30 문서에 타입 정보를 쓰지 않기
- 주석과 변수명에 타입 정보를 적는 것은 피해야 합니다. 타입 선언이 중복되는 것으로 끝나면 다행이지만 최악의 경우는 타입 정보에 모순이 발생하게 됩니다.
- 타입이 명확하지 않은 경우는 변수명에 단위 정보를 포함하는 것을 고려하는 것이 좋습니다(예를 들어 timeMs 또는 temperatureC).
item31 타입 주변에 null 값 배치하기
- 한 값의 null 여부가 다른 값이 null 여부에 암시적으로 관련되도록 설계하면 안 됩니다.
- API 작성 시에는 반환 타입을 큰 객체로 만들고 반환 타입 전체가 null이거나 null이 아니게 만들어야 합니다. 사람과 타입 체커 모두에게 명료한 코드가 될 것입니다.
- 클래스를 만들 때는 필요한 모든 값이 준비되었을 때 생성하여 null이 존재하지 않도록 하는 것이 좋습니다.
- strictNullChecks를 설정하면 코드에 많은 오류가 표시되겠지만, null 값과 관련된 문제점을 찾아낼 수 있기 때문에 반드시 필요합니다.
item32 유니온의 인터페이스보다는 인터페이스의 유니온을 사용하기
- 유니온 타입의 속성을 여러 개 가지는 인터페이스에서는 속성 간의 관계가 분명하지 않기 때문에 실수가 자주 발생하므로 주의해야 합니다.
- 유니온의 인터페이스보다 인터페이스의 유니온이 더 정확하고 타입스크립트가 이해하기 좋습니다.
- 타입스크립트가 제어 흐름을 분석할 수 있도록 타입에 태그를 넣는 것을 고려해야 합니다. 태그된 유니온은 타입스크립트와 매우 잘 맞기 때문에 자주 볼 수 있는 패턴입니다.
item33 string 타입보다 더 구체적인 타입 사용하기
- ‘문자열을 남발하여 선언된’코드를 피합시다. 모든 문자열을 할당할 수 있는 string타입보다는 더 구체적인 타입을 사용하는 것이 좋습니다.
- 변수의 범위를 보다 정확하게 표현하고 싶다면 string 타입보다는 문자열 리터럴 타입의 유니온을 사용하면 됩니다. 타입 체크를 더 엄격히 할 수 있고 생산성을 향상시킬 수 있습니다.
- 객체의 속성 이을 함수 매개변수로 담 때는 string보다 keoyof T를 사용하는 것이 좋습니다.
item34 부정확한 타입보다는 미완성 타입을 사용하기
- 타입 안정성에서 불쾌한 골짜기는 피해야 합니다. 타입이 없는 것보다 잘못된 게 더 나쁩니다.
- 정확하게 타입을 모델링할 수 없다면, 부정확하게 모델링하지 말아야 합니다. 또한 any와 unknown를 구별해서 사용해야 합니다.
item35 데이터가 아닌, API와 명세를 보고 타입 만들기
- 코드의 구석 구석까지 타입 아정성을 얻기 위해 API 또는 데이터 형식에 대한 타입 생성을 고려해야 합니다.
- 데이터에 드러나지 않는 예외적인 경우들이 문제가 될 수 있기 때문에 데이터보다는 명세로부터 코드를 생성하는 것이 좋습니다.
item36 해당 분야의 용어로 타입 이름 짓기
- 가독성을 높이고, 추상화 수준을 올리기 위해서 해당 분야의 용어를 사용해야 합니다.
- 같은 의미에 다른 이름을 붙이면 안 됩니다. 특별한 의미가 있을 때만 용어를 구분해야 합니다.
item37 공식 명칭에는 상표를 붙이기
- 타입스크립트는 구조적 타이핑(덕 타이핑)을 사용하기 때문에, 값을 세밀하게 구분하지 못하는 경우가 있습니다. 값을 구분하기 위해 공식 명칭이 필요하다면 상표를 붙이는 것을 고려해야 합니다.
- 상표 기법은 타입 시스템에서 동작하지만 런타임에 상표를 검사하는 것과 동일한 효과를 얻을 수 있습니다.
item38 any 타입은 가능한 한 좁은 범위에서만 사용하기
- 의도치 않은 타입 안정성의 손실을 피하기 위해서 any의 사용 범위를 최소한으로 좁혀야 합니다.
- 함수의 반환 타입이 any인 경우 타입 안정성이 나빠집니다. 따라서 any 타입을 반환하면 절대 안 됩니다.
- 강제로 타입 오류를 제거하려면 any 대신 @ts-ingnore 사용하는 것이 좋습니다.
item39 any를 구체적으로 변형해서 사용하기
- any를 사용할 때는 정말로 모든 값이 허용되어야만 하는지 면밀히 검토해야 합니다.
- any보다 더 정확하게 모델링 할 수 있도록 any[] 또는 {{[id: string]: any} 또는 () ⇒any 처럼 구체적인 형태를 사용해야 합니다.
item40 함수 안으로 타입 단언문 감추기
- 타입 선언문은 일반적으로 타입을 위험하게 만들지만 상황에 따라 필요하기도 하고 현실적인 해결책이 되기도 합니다. 불가피하게 사용해야 한다면, 정확한 정의를 가지는 함수 안으로 숨기도록 합니다.
item41 any의 진화를 이해하기
- 일반적인 타입들은 정제되기만 하는 밤녀, 암시적 any와 any[] 타입은 진화할 수 있습니다. 이러한 동작이 발생하는 코드를 인지하고 이해할 수 있어야 합니다.
- any를 진화시키는 방식보다 명시적 타입 구문을 사용하는 것이 안전한 타입을 유지하는 방법입니다.
item42 모르는 타입의 값에는 any 대신 unknown을 사용하기
- unknown은 any 대신 사용할 수 있는 안전한 타입입니다. 어떠한 값이 있지만 그 타입을 알지 못하는 경우라면 unknown을 사용하면 됩니다.
- 사용자가 타입 단언문이나 타입 체크를 사용하도록 강제하려면 unknown을 사용하면 됩니다.
- {}, obejct, unknown의 차이점을 이해해야 합니다.
item43 몽키 패치보다는 안전한 타입을 사용하기
- 전역 변수나 DOM에 데이터를 저장하지 말고, 데이터를 분리하여 사용해야 합니다.
- 내장 타입에 데이터를 저장해야 하는 경우, 안전한 타입 접근법 중 하나(보강이나 사용자 정의 인터페이스로 단언)를 사용해야 합니다.
- 보강의 모듈 영역 문제를 이해해야 합니다.
item44 타입 커버리지를 추적하여 타입 안정성 유지하기
- noImplicitAny가 설정되어 있어도, 명시적 any 또는 서드파티 타입 선언(@types)을 통해 any 타입은 코드 내에 여전히 존재할 수 있다는 점을 주의해야 합니다.
- 작성한 프로그램의 타입이 얼마나 잘 선언되었는지 추적해야 합니다. 추적함으로써 any의 사용을 줄여 나갈 수 있고 타입 안정성을 꾸준히 높일 수 있습니다.
item45 devDependencies에 typescript와 @types 추가하기
- 타입스크립트를 시스템 레벨로 설치하면 안 됩니다. 타입스크립트를 프로젝트devDependencies에 포함시키고 팀원 모두가 동일한 버전을 사용하도록 해야 합니다.
- @types 의존성은 dependencies 가 아니라 devDependencies에 포함시켜야 ㅎ바니다. 런타임에 @types가 필요한 경우라면 별도의 작업이 필요할 수 있습니다.
item46 타입 선언과 관련된 세 가지 버전 이해하기
- @types 의존성과 관련된 세 가지 버전이 있습니다. 라이브러리 버전, @types 버전, 타입스크립트 버전입니다.
- 라이브러리를 업데이트하는 경우, 해당 @types 역시 업데이트해야 합니다.
- 타입 선언을 라이브러리에 포함하는 것과 DefinitelyTyped에 공개하는 것 사이의 장단점을 이해해야 합니다. 타입스크립트로 작성된 라이브러리라면 타입 선언을 자체적으로 포함하고, 자바스크립트로 작성된 라이브러리라면 타입 선언을 Definitely Types에 공개하는 것이 좋습니다.
item47 공개 API에 등장하는 모든 타입을 익스포트하기
- 공개 메서드에 등장한 어떤 형태의 타입이든 익스포트합시다. 어차피 라이브러리 사용자가 추출할 수 있으므로, 익스포트하기 쉽게 만드는 것이 좋습니다.
item48 API 주석에 TSDoc 사용하기
- 익스포트된 함수, 클래스, 타입에 주석을 달 때는 JSDoc/TsDoc 형태를 사용합시다. JSDoc/TsDoc 형태의 주석을 달면 편집기가 주석 정보를 표시해 줍니다.
- @param, @returns 구문과 문서 서식을 위해 마크다운을 사용할 수 있습니다.
- 주석에 타입 정보를 포함하면 안 됩니다.(아이템 30)
item49 콜백에서 this에 대한 타입 제공하기
- this 바인디잉 동작하는 원리를 이해해야 합니다.
- 콜백 함수에서 this를 사용해야 한다면, 타입 정보를 명시해야 합니다.
item50 오버로딩 타입보다는 조건부 타입을 사용하기
- 오버로딩 타입보다 조건부 타입을 사용하는 것이 좋습니다. 조건부 타입은 추가적인 오버로딩 없이 유니온 타입을 지원할 수 있습니다.
item51 의존성 분리를 위해 미러 타입 사용하기
- 필수가 아닌 의존성을 분리할 때는 구조적 타이핑을 사용하면 됩니다.
- 공개한 라이브러리를 사용하는 자바스크립트 사용자가 @types 의존성을 가지지 않게 해야 합니다. 그리고 웹 개발자가 NodeJS 관련된 의존성을 가지지 않게 해야 합니다.
item52 테스팅 타입의 함정에 주의하기
- 타입을 테스트할 때는 특히 함수 타입의 동일성(equality)과 할당 가능성(assignability)의 차이점을 알고 있어야 합니다.
- 콜백이 있는 함수를 테스트할 때, 콜백 매개변수의 추론된 타입을 체크해야 합니다. 또한 this가 API의 일부분이라면 역시 테스트해야 합니다.
- 타입 관련된 테스트에서 any를 주의해야 합니다. 더 엄격한 테스트를 위해 dtslint 같은 도구를 사용하는 것이 좋습니다.
item53 타입스크립트 기능보다는 ECMAScript 기능을 사용하기
- 일반적으로 타입스크립트 코드에서 모든 타입정보를 제거하면 자바스크립트가 되지만, 열거형, 매개변수 속성, 트리플 슬래시 임포트, 데코레이터는 타입 저보를 제거한다고 자바스크립트가 되지는 않습니다.
- 타입스크립트의 역할을 명확하게 하려면, 열거형, 매개변수 속성, 트리플 슬래시 임포트, 데코레이터는 사용하지 않는 것이 좋습니다.
item54 객체를 순회하는 노하우
- 객체를 순회할 때, 키가 어 타입인지 정확히 파악하고 있다면 let k: keyof T와 for-in 루프를 사용합시다. 함수의 매개변수로 쓰이는 객체에는 추가적인 키가 존재할 수 있다는 점을 명심합시다.
- 객체를 순회하며 키와 값을 얻는 가장 일반적인 방법은 Object.entries를 사용하는 것입니다.
item55 DOM 계층 구조 이해하기
- 자바스크립트를 사용할 때는 신경 스지 않았겠지만, DOM에는 타입 계층 구조가 있습니다. DOM 타입은 타입스크립트에서 중요한 정보이며, 브라우저 관련 프로젝트에서 타입스크립트를 사용할 때 유용합니다.
- Node, Element, HTMLElment, EventTarget 간의 차이점, 그리고 Event와 Mouse Event의 차이점을 알아야 합니다.
- DOM 엘리먼트와 이벤트에는 충분히 구체적인 타입 정보를 사용하거나, 타입스클비트가 추론할 수 있도록 문맥 정보를 활용해야 합니다.
item56 정보를 감추는 목적으로 private 사용하지 않기
- public, protected, private 접근 제어자는 타입 시스템에서만 강제될 뿐입니다. 런타임에는 소용이 없으며 단언문을 통해 우회할 수 있습니다. 접근 제어자로 데이터를 감추려고 해서는 안 됩니다.
- 확실히 데이터를 감추고 싶다면 클로저를 사용해야 합니다.
item57 소스맵을 사용하여 타입스크립트 디버깅하기
- 원본 코드가 아닌 변환된 자바스크립트 코드를 디버깅하지 맙시다. 소스맵을 사용해서 런타임에 타입스크립트 코드를 디버깅합시다.
- 소스맵이 최종적으로 변환된 코드에 완전히 매핑되었는지 확인합시다.
- 소스맵에 원본 코드가 그대로 포함되도록 설정되어 있을 수도 있습니다. 공개되지 않도록 설정을 확인합시다.
item58 모던 자바스크립트로 작성하기
- 타입스크립트 개발 환경은 모던 자바스크립트도 실행할 수 있으므로 모던 자바스크립트의 최신 기능들을 적극적으로 사용하길 바랍니다. 코드 품질을 향상시킬 수 있고, 타입스크립트의 타입 추론도 더 나아집니다.
- 타입스크립트 개발 환경에서는 컴파일러와 언어 서비스를 통해 클래스, 구조 분해, async/await 같은 기능을 쉽게 배울 수 있습니다.
- ‘use strict’는 타입스크립트 컴파일러 수준에서 사용되므로 코드에서 제거해야 합니다.
- TC39의 깃헙 저장소와 타입스크립트의 릴리스 노트를 통해 최신 기능을 확인할 수 있습니다.
item59 타입스크립트 도입 전에 @ts-check와 JSDoc으로 시험해보기
- 파일 상단에 // @ts-check를 추가하면 자바스크립트에서도 타입 체크를 수행할 수 있습니다.
- 전역 선언과 서드파티 라이브러리의 타입 선언을 추가하는 방법을 익힙니다.
- JSDoc 주석을 잘 활용하면 자바스크립트 상태에서도 타입 단언과 타입 추론을 할 수 있습니다.
- JSDoc 주석은 중간 단계이기 때문에 너무 공들일 필요는 없습니다. 최종 목표는 .ts로 된 타입스크립트 코드임을 명시합니다.
item60 allowJS로 타입스크립트와 자바스크립트 같이 사용하기
- 점진적 마이그레이션을 위해 자바스크립트와 타입스크립트를 동시에 사용할 수 있게 allowJS 컴파일러 옵션을 사용합시다.
- 대규모 마이그레이션 작업을 시작하기 전에, 테스트와 빌드 체인에 타입스크립트를 적용해야 합니다.
item61 의존성 관계에 따라 모듈 단위로 전환하기
- 마이그레이션의 첫 단계는, 서드파티 모듈과 외부 API 호출에 대한 @types를 추가하는 것입니다.
- 의존성 관계도의 아래에서부터 위로 올라가며 마이그레이션을 하면 됩니다. 첫 번째 모듈은 보통 유틸리티 모듈입니다. 의존성 관계도를 시각화하여 진행 과정을 추적하는 것이 좋습니다.
- 이상한 설계를 발견하더라도 리팩터링을 하면 안됩니다. 마이그레이션 작업은 타입스크립트 전환에 집중해야 하며, 나중의 리팩터링을 위해 목록을 만들어 두는 것이 좋습니다.
- 타입스크립트로 전환하며 발견하게 되는 일반적인 오류들을 놓치지 않아야 합니다. 타입 정보를 유지하기 위해 필요에 따라 JSDoc 주석을 활용해야 할 수 있습니다.
item62 마이그레이션의 완성을 위해 noImplicitAny 설정하기
- noImplicitAny설정을 활성화하여 마이그레이션의 마지막 단계를 진행해야 합니다. noImplicitAny 설정이 없다면 타입 선언과 관련된 실제 오류가 드러나지 않습니다.
- noImplicitAny를 전면 적용하기 전에 로컬에서부터 타입 오류를 점진적으로 수정해야 합니다. 엄격한 타입 체크를 적용하기 전에 팀원들이 타입스크립트에 익숙해질 수 있도록 시간을 줍시다.