
타입가드는 변수 또는 표현식의 타입 범위를 좁혀나가 더 정확하고 명시적인 타입 추론을 가능하게 하며 복잡한 타입을 작은 타입으로 축소하여 타입의 안전성을 높일 수 있습니다.
이러한 타입가드는 대표적으로 자바스크립트 연산자를 사용한 타입가드와 사용자 정의 타입가드로 나뉘는데요.
자바스크립트 연산자를 이용한 3가지의 대표적인 타입가드 연산자와 사용자 정의 타입가드를 사용하는 연산자를 말해주세요.
그리고 각각의 연산자는 어떤 상황에서 사용이 되는지 간단하게 설명해주세요.



자바스크립트 연산자를 활용한 타입가드
런타임에 유효한 타입 가드를 만들기 위해 사용한다.
1. typeof
원시 타입을 추론할 때 사용한다.
let x: any = "Hello TypeScript!"; if (typeof x === "string") { console.log(x); // "Hello TypeScript!" } else { console.log("x is not a string"); };2. instanceof
인스턴스화된 객체 타입을 판별할 때 사용한다.
class MyClass {} let x: any = new MyClass(); if (x instanceof MyClass) { console.log(x); } else { console.log("x is not an instance of MyClass"); };3. in
객체의 속성이 있는지 없는지에 따른 구분할 때 사용한다.
let protector = { name: "철수", mbti: 'ESTJ'}; if ("mbti" in protector) { console.log(`방범대원 ${protector.name}의 MBTI는 ${protector.mbti}입니다.`); // "방범대원 철수의 MBTI는 ESTJ입니다." } else { console.log("mbti does not exist in protector"); };
사용자 정의 타입가드
사용자가 직접 어떤 타입으로 값을 좁힐지를 직접 지정하는 방식이다.
is 연산자를 활용한 예시
function isNumber(value: any): value is number { return typeof value === 'number'; } let myValue: any = 5; if (isNumber(myValue)) { console.log('myValue is a number'); // 출력 } else { console.log('myValue is not a number'); }; myValue = 'five'; if (isNumber(myValue)) { console.log('myValue is a number'); } else { console.log('myValue is not a number'); // 출력 };
본문에서 교차 타입은 기존 타입을 합쳐 필요한 모든 기능을 가진 하나의 타입을 만드는 것으로 이해할 수 있다고 말했습니다.
주어진 type을 이용해 새로운 타입을 정의하고, 이를 만족하는 객체를 생성해보세요.
type Book = {
title: string;
author: string;
};
type SaleItem = {
price: number;
};
// 1. 교차 타입을 사용하여 'BookSaleItem' 타입을 정의하세요
// 2. 'BookSaleItem' 타입의 객체 'firstItem'을 생성하세요.


type Book = { title: string; author: string; }; type SaleItem = { price: number; }; // 1. 교차 타입을 사용하여 'BookSaleItem' 타입을 정의하세요 type BookSaleItem = Book & SaleItem; // 2. 'BookSaleItem' 타입의 객체 'firstItem'을 생성하세요. const firstItem: BookSaleItem = { title: "우아한 타입스크립트 with 리액트", author: '우아한형제들', price: 28800, }여기서
BookSaleItem타입은Book과SaleItem타입을 교차하여 만든 새로운 타입입니다.이 타입은
Book타입의title과author속성뿐만 아니라SaleItem타입의price속성도 가지고 있어야 합니다.
firstItem객체는 이BookSaleItem타입을 따르고 있으며, 모든 필요한 속성(title, author, price)을 포함하고 있습니다.이 예제는 교차 타입을 사용하여 복합적인 타입을 만들고, 이 타입에 맞는 객체를 어떻게 생성하는지를 잘 보여줍니다.
다음은 식별할 수 있는 유니온(Discriminated Unions)을 이용하여 타입을 좁힌 예제입니다.
type IPhone = {
name: "아이폰",
version: number,
}
type AirPod = {
name: "에어팟",
version: number,
noisecancel: boolean,
}
type AppleProductType = IPhone | AirPod;
const products: AppleProductType[] = [
{ name: "아이폰", version: 15 },
{ name: "아이폰", version: 15, noisecancel: true }, // 🚨 error
];
위 예제는 타입 좁히기를 무사히 성공하여 products 배열의 요소 중 두번째는 에러를 출력하도록 만들었습니다.
그렇다면 (1) 왜 타입 에러를 갖게 하는 것이 좋은 코드인지에 대한 설명과 (사실 이 부분은 복습이여요)
(2) 위 코드가 식별할 수 유니온을 사용하기 이전에 아무 타입 에러도 뱉지 않는 코드는 어땠을 것 같은지 역으로 추론해주세요.



타입 에러를 갖게함으로써 코드의 안정성을 보장하고 잘못된 타입을 예방하여 버그를 줄이는 데 도움이 된다. 이는 개발자가 코드의 의도를 명확하게 표현하고, 예상치 못한 오류를 방지할 수 있게 해준다.
type IPhone = { version: number, } type AirPod = { version: number, noisecancel: boolean, } type AppleProductType = IPhone | AirPod; const products: AppleProductType[] = [ { version: 15 }, { version: 15, noisecancel: true }, // 에러발생 x ];