🧐 타입스크립트
- 인터프리터로 실행되는 것도 아니고, 저수준 언어로 컴파일 되는 것도 아님.
- 자바스크립트로 컴파일 되며, 실행도 자바스크립트로 됨.
📖 아이템 1. 타입스크립트와 자바스크립트의 관계
- 타입스크립트는 자바스크립트의 상위 집합(superset)이다.
- 타입스크립트 프로그램이지만 자바스크립트가 아닌것도 존재한다.
- 타입 시스템의 목표
- 런타임에 오류를 발생시킬 코드를 미리 찾아내는 것 (타입 스크립트가 정적 타입 시스템인 것의 특징)
- 타입 체커는 추가적인 타입 구문 없이도 오류를 찾아낸다. (꽤 훌륭한 해결책을 제시함)
- 타입 구문을 추가한다면 더 많은 오류를 찾을 수 있음 (항상 정확하지는 않음) => states를 명시적으로 선언하여 타입을 지정해주면 오류가 어디서 발생했는지, 해결책이 올바른지에 관한 고민을 안해도 됨.
- 타입스크립트의 타입 시스템은 자바스크립트의 런타임 동작을 모델링한다.
- 단순히 모델링하는 것 뿐만 아니라 의도치 않은 이상한 코드가 오류로 이어질 수 있다고 알려줌
- 하지만 타입 체커를 통과하면서도 런타임 오류를 발생시키는 코드도 충분히 존재할 수 있음
📖 아이템 2. 타입스크립트 설정 이해하기
- 100개 이상의 설정들이 있고, command나 tsconfig.json을 만들어 사용 가능하다. ex) tsc --noImplicitAny program.ts, compilerOptions: {"noImplicitAny": true}
- tsc --init으로 간단하게 설정 가능
- 제대로 이해하려면 noImplicitAny 와 strictNullChecks를 이해해야함
- noImplicitAny: 변수들이 미리 정의된 타입을 가지고 있어야 하는지 여부를 제어함. => 타입이 없으면 any타입을 지정해준 것과 같음 => any 타입을 써버리면 타입 체커는 무의미해짐 => 쓰는 것을 강추한다! (자바스크립트에서 타입스크립트로 마이그레이션 할때는 꺼야됨)
- strictNullChecks: null과 undefined가 모든 타입에서 허용되는지 확인하는 설정 => null을 허용하지 않으려면, 이 값이 어디서 부터 왔는지 찾고, null 체크나 예외 코드를 추가해야 함
📖 아이템 3. 코드 생성과 타입이 관계없음을 이해하기
- 타입스크립트 컴파일러의 역할
- 최신 타입스크립트/ 자바스크립트를 브라우저에서 동작할 수 있도록 구버전의 자바스크립트로 트랜스파일 한다.
- 코드의 타입 오류를 체크한다. => 이 두가지는 완벽하게 독립적임
- 두 가지가 완벽하게 독립적이라 일어날 수 있는 일
- 타입오류가 있는 코드도 컴파일이 가능하다.
- 타입스크립트의 오류는 warning과 비슷해서 빌드를 멈추지는 않음
- 오류가 있을때 컴파일 하지 않는 옵션: noEmitOnError
- 런타임에는타입 체크가 불가능하다.
- 런타임에 타입 정보 유지하는 방법들이 있음
- 쓰고싶은 옵션이 있는지 체크
- 런타임에 접근 가능한 타입 정보를 명시적으로 저장하는 '태그' 기법
- 타입 연산은 런타임에 영향을 주지 않음
- string 또는 number 타입인 값을 항상 number로 정제하는 경우
- as number와 같은 타입 단언문은 값을 정제하기 위해 사용하면 안됨
- 자바스크립트 연산을 통해 변환을 수행해야 함
- 런타임 타입은 선언된 타입과 다를 수 있음
- 타입 선언문은 런타임에 제거됨. 그래서 타입이 달라질 수 있음
- 선언된 타입이 언제든지 달라질 수 있다는 것을 알고 있어야 함.
- 타입스크립트 타입으로는 함수를 오버로드 할 수없음
- 함수 오버로딩은 타입수준에서만 동작함 => 하나의 함수에 여러개의 선언문을 작성가능, 하지만 구현체는 오직 하나임
- 타입 정보 제공은 자바스크립트로 변환되면서 제거되며, 구현체만 남게되어 결론적으로 오버로딩 X
- 타입스크립트 타입은 런타임 성능에 영향을 주지 않음
- 런타임 오버헤드가 없는 대신 빌트타임 오버로드가 있음
- 오래된 런타임 환경을 지원하기 위해 호환성을 높이고 성능 오버헤드를 감안할지, 호환성을 버리고 성능 중심의 네이티브 구현체를 선택할지를 고를 수도 있음
📖 아이템 4. 구조적 타이핑에 익숙해지기
- 자바스크립트는 덕 타이핑 기반.
- 타입스크립트가 이를 모델링하기 위해 구조적 타이핑을 사용한다.
- 구조적 타이핑: 어떤 interface에 할당 가능한 값이라면 타입 선언에 명시적으로 나열된 속성들을 가지고 있을 것이다. (타입은 봉인되어 있지 않다.)
- 객체의 구조가 호환되면 두 객체의 관계를 설명해주지 않아도 사용 가능한 것. (interface도)
- 이런 구조적 타이핑의 문제에서 객체를 순회하는 루프는 문제가 발생할 확률이 높음. => 모든 속성을 각각 사용하는 구현이 더 나음
- 구조적 타이핑은 클래스와 관련된 할당문에서도 문제가 발생함
- 구조적으로 필요한 속성과 생성자가존재하면 문제가 없다고 여겨짐
- 테스트를 작성할 때에는 구조적 타이핑이 유리함 (유닛 테스트)
- 실제 환경에서 쓰일 수 있는 인터페이스를 만들어 놔서 사용
- 구조적 타이핑은 라이브러리 간의 의존성을 완전히 분리할 수 있다는 장점이 있음.
📖 아이템 5. any 타입 지양하기
- 타입스크립트의 타입 시스템은 점진적이고 선택적이다.
- 타입 선언에 추가적인 시간을 쏟고 싶지 않을 때 => any or 타입 선언문 (as any)를 씀
- 특별한 경우를 제외하고는 any 타입을 쓰지 말자!
- 무분별한 any 사용이 위험한 이유
- any 타입에는 타입 안정성이 없다.
- 타입체커가 선언에 따라 판단하는게 다를 것이고, 혼돈을 줄 수 있다.
- any는 함수 시그니처를 무시해버린다.
- any 타입에는 언어 서비스가 적용되지 않는다.
- 어떤 심벌에 타입이 있다면 타입스크립트 언어 서비스는 자동완성 기능과 적절한 도움말을 제공한다
- 하지만 any타입은 안해준다.
- 이름 변경 기능도 해당 interface 타입을 사용한 코드 까지 바꿔주는데 이 기능을 사용할 수 없다.
- any 타입은 코드 리팩터링 때 버그를 감춰준다.
- 타입 체크를 통과했어도, 중간에 any로 매개변수를 받는 함수가 존재하면 런타임에는 오류를 발생시킬 수 있다.
- any는 타입 설계를 감춰버린다.
- 특히 객체를 정의할 때, 상태 객체의 설계를 감춰버린다.
- 깔끔하고 정확하고 명료한 코드 작성을 위해서는 제대로 된 타입 설계는 필수다.
- any는 타입시스템의 신뢰도를 떨어뜨린다.
- any타입을 쓰지 않으면 런타임에 발견될 오류를 미리 잡고 신뢰도를 높일 수있다.
- 반대로 any타입이 많이 존재하면 자바스크립트보다 일을 더 어렵게 만들 수도 있다.
let age: number; age = '12' as any; age += 1; // => 런타임에 정상, '121' 원하던 결과가 아님
- 함수를 작성할때는 시그니처를 명시해야 함. 호출하는 쪽은 약속된 타입의 입력을 제공하고, 함수는약속된 타입의 출력을 반환한다.
- 하지만, any타입을 사용하면 이런 약속을 어길 수 있음
function a(birthDay: Date): number {...}; let birthDay: any = '1998-09-19'; a(birthday); // 정상 => string이 아닌 Date타입 이여야 하는데 돌아감
- 최대한 사용을 피하자!