🔸 웹사이트와 웹 애플리케이션
- 웹사이트는 수집된 데이터 및 정보를 특정 페이지에 표시하기 위한 정적인 웹이지만,
- 웹 애플리케이션은 사용자와 상호작용하는 쌍방향 소통의 웹이다. (댓글, 검색, 채팅, 좋아요 등...)
🔸 자바스크립트의 한계
- 자바스크립트 특징 중 하나는 동적 타입 언어. 따라서 변숫값이 할당될 때 해당 값의 타입에 따라 변수 타입이 결정된다.
- 숫자 a, b의 합을 반환하는 sumNumber라는 함수를 만들었을 때, 자바스크립트에서는 a, b에 문자열을 입력해도 오류가 나지 않고 'ab'라는 반환값을 준다. -> 개발자의 의도와는 다르게 동작할 수 있음!
🔸 컴파일타임과 런타임
- 컴파일타임: 기계가 소스코드를 이해할 수 있도록 기계어로 변환되는 시점
- 런타임: 컴파일타임 이후 변환된 파일이 메모리에 적재되어 실행되는 시점
🔸 구조적 서브타이핑과 명목적 타이핑
- 구조적 서브타이핑: 객체가 가지고 있는 속성을 바탕으로 타입을 구분. 이름이 다른 객체라도 가진 속성이 동일하다면 서로 호환 가능한 동일 타입으로 여김! -> 타입이 계층 구조로부터 자유로움. 유연하고 편리하다는 장점! -> Typescript
- 명목적 타이핑: 타입의 구조가 아닌 타입의 이름만을 가지고 구별. 두 변수는 같은 이름의 데이터 타입으로 선언된 경우에만 서로 호환됨! -> C++, JAVA
🔸 any와 unknown 타입
- any타입은 타입스크립트 내 모든 타입의 종류를 포함하는 가장 상위 타입으로, 어떤 타입 값이든 할당할 수 있다.
- 타입스크립트 컴파일 옵션의 noImplicitAny 값이 true인 경우엔 any타입 추론을 허용하지 않고 에러를 발생한다. -> 정확한 타이핑을 위해 해당 옵션 true로 설정하는 것이 좋음!
- unknown도 어떤 타입이든 할당 가능하나, 해당 함수를 실행할 때에는 에러가 발생한다. -> 타입 검사를 엄격하게 강제하기 때문에 any보다 더 안전
- 어떤 값을 받아올지 또는 넘겨줄지 정할 수 없을 때, 임시로 지정해야될 때 사용
🔸 never 타입
- 값을 반환할 수 없는 타입
- 에러를 던지는 경우(값을 반환하는 경우가 아님), 무한히 함수가 실행되는 경우 사용
🔸 타입 확장
- interface -> extends, type -> & or | (유니온 타입, 교차 타입) 으로 타입 확장 가능
- extends와 type의 확장은 100% 상응하지 않는다.
type DeliveryTip = {
tip: number;
};
type Filter = DeliveryTip & {
tip: string;
};
위 코드에서 interface의 선언 및 확장으로 변경하면 tip 타입이 호환되지 않는다는 에러가 발생한다.
하지만 type으로 선언하면 에러가 발생하지 않는데, 이때 tip의 속성 타입은 never이다.
- 타입 확장(추가)를 별도의 타입을 만들어 확장시키지 않고 text?: string 이런 식으로 한다면 모든 원소가 text 속성을 가지고 있지 않으므로 에러가 발생 -> 타입을 확장해서 사용하는 것이 좋다!
🔸 타입 가드
- typeof: 원시 타입(string, number, boolean 등) 추론시 사용 -> 복잡한 타입을 검증하기엔 한계가 존재하기 때문
- instanceof: 인스턴스화된 객체 타입 판별시 사용
- in: 객체의 속성이 있는지 없는지 판별
- is 연산자로 사용자 정의 타입 가드 만들어 활용
const isDestinationCode = (x: string): x is DestinationCode =>
destinationCodeList.includes(x);
🔸 식별할 수 있는 유니온
- 여러 타입들을 유니온 타입으로 만들었을 때, 각각의 타입들이 서로 호환되지 않도록 만들어야 된다
-> 그렇지 않으면 모든 속성이 포함된 잘못된 객체를 전달해도 타입 에러가 발생하지 않아 예상치 못한 오류 발생가능
- 이를 해결하기 위해 각각의 타입을 구분할 방법이 필요하다. 각각에 판별자를 달아 포함 관계를 제거하는 것이다!
type TextError = {
errorType: "TEXT";
errorCode: string;
...
}
type ToastError = {
errorType: "TOAST";
errorCode: string;
...
}
- 여기서 식별할 수 있는 유니온의 판별자는 유닛 타입으로 선언되어야 정상적으로 동작한다.
✅유닛 타입: 다른 타입으로 쪼개지지 않고 오직 하나의 정확한 값을 가지는 타입.
ex) null, undefined, true, 1
🔸 Exhaustiveness Checking
- Exhaustiveness Checking으로 정확한 타입 분기를 유지할 수 있다.
- 타입에 대한 분기 처리를 수행할 때, 모든 케이스에 대해 분기 처리를 해야 유지보수 측면에서 안전하다고 생각되는 상황이 생긴다. 이때 Exhaustiveness Checking을 통해 모든 케이스에 대한 타입 검사를 강제할 수 있다.
if (productPrice === "1000") return ~~
if ~~~
else {
exhaustiveCheck(productPrice);
return "상품권";
}
};
const exhaustiveCheck = (param: never) => {
throw new Error("type error!");
};
- 만약 분기처리를 하지 않은 값이 있다면, exhaustiveCheck함수에서 값이 들어오므로 에러를 뱉는다.
- 매개변수 타입이 never = 매개변수로 어떤 값도 받을 수 없음을 뜻함