
2025 / 03 / 04
오늘 수업 시간에는 Intersection과 Type Narrowing에 대해 배웠습니다.
두 내용 다 처음 보는 내용이라 막막하긴 했지만 이해하기 위해 여러 번 읽어보았습니다.
제대로 이해한 것인지는 모르겠지만 최대한 이해하기 쉽게 정리해서 포스팅하겠습니다!
Intersection Type
- 인터섹션 타입은 여러 타입을 결합해서 하나의 새로운 타입을 만드는 방법입니다.
- 여러 타입을
&기호로 결합하여 하나의 객체나 값이 두 가지 이상의 특성을 가지도록 만드는 것을 의미합니다.
- 인터섹션 타입을 만들려면
&기호를 사용합니다.- 결합된 타입은 두 타입에 속하는 모든 속성을 갖게 됩니다.
interface Human {
name: string;
age: number;
}
interface Contacts {
phone: string;
email: string;
}
type User = Human & Contacts; // Human과 Contacts 타입을 결합
let user1: User = {
name: "jinha",
age: 23,
phone: "010-6551-8374",
email: "nyang@naver.com",
};
- 원시 타입(number, string 등)을 결합하려고 하면 문제가 발생합니다.
- number와 string을 동시에 가질 수 없기 때문에 결합할 수 없습니다.
- 이럴 때는 never 타입이 반환됩니다.
type NumAndString = number & string; // 결합할 수 없음
// let numAndString: NumAndString = 1;
// 오류: number와 string은 결합할 수 없음
- 인터섹션 타입을 활용하면 하나의 타입을 다른 타입으로 확장할 수 있습니다.
type ProductItem = {
id: number;
name: string;
type: string;
};
type ProductItemWithDiscount = ProductItem & {
discountAmount: number;
};
const item: ProductItemWithDiscount = {
id: 1,
name: "item1",
type: "type1",
discountAmount: 10,
};
- 여러 타입을
&연산자로 결합하여 새로운 타입을 만들 때 사용됩니다.- 결합된 타입은 모든 속성을 포함합니다.
- 원시 타입(number와 string 등)은 서로 결합할 수 없습니다.
- 다른 타입을 확장하는 데 유용하게 사용할 수 있습니다.
- 변수가 여러 타입 중 하나를 가질 때, 조건에 따라 타입의 범위를 좁혀주는 것을 의미합니다.
- 타입 네로잉을 통해 타입 추론이 더 정확하게 이루어집니다.
- 타입 네로잉의 다양한 기법에 대해 예시와 함께 정리해보겠습니다.
할당을 통한 타입 좁히기
- 변수에 특정 값을 할당함으로써 타입을 좁힙니다.
- number | string 타입의 변수에 문자열을 할당하면 그 변수는 string 타입으로 좁혀집니다.
let value: number | string = "hello";
value.length; // string 타입으로 추론됨
typeof를 통한 타입 좁히기
- typeof 연산자를 사용하여 원시 타입을 좁힐 수 있습니다.
- 해당 값이 string, number, boolean 등 특정 원시 타입인지 확인하고 타입을 좁힙니다.
let value: number | string = Math.random() > 0.5 ? 123 : "hello";
if (typeof value === "string") {
// value는 이제 string 타입
console.log(value.length); // string만 사용 가능
} else {
// value는 number 타입
console.log(value.toFixed(2)); // number만 사용 가능
}
참 / 거짓 판별을 통한 타입 좁히기
- 값이 null, undefined, false 등 falsy한 값인지를 체크하여 타입을 좁힙니다.
- 조건문에서 변수가 falsy한 값을 가지면 null 혹은 undefined 타입으로 좁혀주고, truthy한 값을 가지면 그 값의 타입을 유지합니다.
let value: null | string[] = Math.random() > 0.5 ? null : ["hello"];
if (value) {
// value는 이제 string[] 타입
console.log(value[0]); // string[]만 사용 가능
} else {
// value는 null
console.log("No data");
}
같은 값을 비교하여 타입 좁히기
- 두 변수가 동일한 값을 가지면 그 타입을 정확히 추론할 수 있습니다.
let value1: number | string = Math.random() > 0.5 ? 123 : "hello";
let value2: string | boolean = Math.random() > 0.5 ? "hello" : true;
if (value1 === value2) {
// value1과 value2는 이제 string 타입
console.log(value1.length); // string만 사용 가능
} else {
console.log(value1, value2); // 여전히 number | string, string | boolean
}
in 연산자를 통한 타입 좁히기
- in 연산자를 사용하여 객체에 특정 프로퍼티가 존재하는지를 확인하고, 타입을 좁힐 수 있습니다.
interface Human {
name: string;
age: number;
}
interface Dog {
name: string;
type: string;
}
let person: Human = { name: "John", age: 30 };
let dog: Dog = { name: "Buddy", type: "Poodle" };
let humanOrDog: Human | Dog = Math.random() > 0.5 ? person : dog;
if ("type" in humanOrDog) {
// humanOrDog는 이제 Dog 타입
console.log(humanOrDog.type);
} else {
// humanOrDog는 이제 Human 타입
console.log(humanOrDog.age);
}
instanceof를 통한 타입 좁히기
- instanceof를 사용하여 객체가 특정 클래스의 인스턴스인지 확인하고, 타입을 좁힐 수 있습니다.
let value: Date | string = Math.random() > 0.5 ? new Date() : "2025-03-05";
if (value instanceof Date) {
// value는 Date 타입
console.log(value.toISOString());
} else {
// value는 string 타입
console.log(value.toUpperCase());
}
구분된 유니온을 통한 타입 좁히기
- 구분된 유니온(Discriminated Union)은 각 타입에 고유한 값을 할당하여, switch문이나 if문으로 타입을 좁힐 수 있는 방법입니다.
type Dog = { type: "dog"; name: string };
type Cat = { type: "cat"; name: number };
let animal: Dog | Cat = Math.random() > 0.5 ? { type: "dog", name: "Buddy" } : { type: "cat", name: 123 };
switch (animal.type) {
case "dog":
// animal은 Dog 타입
console.log(animal.name); // string
break;
case "cat":
// animal은 Cat 타입
console.log(animal.name); // number
break;
default:
const check: never = animal; // never 타입을 사용해 안전성 보장
}
- 오늘 배운 내용을 가지고 간단한 예제 문제를 풀어보았습니다.
- 숫자 또는 문자열을 받은 함수 작성합니다.
- typeof를 사용하여 네로잉 구현합니다.
/** function formatValue(value: string | number): string { / 여기에 타입 내로잉을 활용해 구현하세요./ } 결과 : console.log(formatValue(42)); // "숫자: 42" console.log(formatValue("hello")); // "문자열: hello" */
function formatValue(value: string | number): string {
if (typeof value === "string") {
return `문자열: ${value}`; // 문자열일 경우
} else {
return `숫자: ${value}`; // 숫자일 경우
}
}
console.log(formatValue(42));
console.log(formatValue("hello"));
- in 연산자를 활용합니다.
/** type Car = { fuel: string }; type Bike = { pedal: boolean }; function getVehicleType(vehicle: Car | Bike): string { // 타입 내로잉을 활용해 구현 } 결과 : console.log(getVehicleType({ fuel: "Gasoline" })); // "자동차 연료: Gasoline" console.log(getVehicleType({ pedal: true })); // "자전거는 페달이 있음" */
type Car = { fuel: string };
type Bike = { pedal: boolean };
function getVehicleType(vehicle: Car | Bike): string {
if ("fuel" in vehicle) {
return `자동차 연료 : ${vehicle.fuel}`;
} else {
return `자전거는 페달이 있음`;
}
}
console.log(getVehicleType({ fuel: "Gasoline" }));
console.log(getVehicleType({ pedal: true }));
- 구분된 유니온을 활용합니다.
/** type Dog = { type: "dog"; sound: string }; type Cat = { type: "cat"; sound: string }; type Bird = { type: "bird"; sound: string }; function getAnimalSound(animal: Dog | Cat | Bird): string { // 타입 내로잉을 활용해 구현하세요. } 결과 : console.log(getAnimalSound({ type: "dog", sound: "멍멍" })); // "멍멍" console.log(getAnimalSound({ type: "cat", sound: "야옹" })); // "야옹" console.log(getAnimalSound({ type: "bird", sound: "짹짹" })); // "짹짹" */
type Dog = { type: "dog"; sound: string };
type Cat = { type: "cat"; sound: string };
type Bird = { type: "bird"; sound: string };
function getAnimalSound(animal: Dog | Cat | Bird): string {
switch (animal.type) {
case "dog":
return animal.sound;
case "cat":
return animal.sound;
case "bird":
return animal.sound;
default:
return "";
}
}
console.log(getAnimalSound({ type: "dog", sound: "멍멍" }));
console.log(getAnimalSound({ type: "cat", sound: "야옹" }));
console.log(getAnimalSound({ type: "bird", sound: "짹짹" }));
39일차 후기
- 인터섹션을 배울 때까지는 괜찮았는데 타입 네로잉은 종류가 많아서 배우다가 살짝 헷갈리는 부분도 생겨서 복습을 여러 번 해야겠다고 생각했습니다..૮( ྀིˊ ᵔ ˋ)ა
- 오늘 내용도 어려운 부분은 별로 없었는데 이론을 배우고 바로 실습 문제에 적용해보려고 하다보니 멈칫하는 부분은 어쩔 수 없이 생기는 것 같습니다.
- 그래도 고민해서 결국은 원하는 결과 값을 얻어냈습니다!! 기분이 너무 좋았습니다.
- 수업 들으면서 생각했는데 "네로잉"이라는 이름이 참 귀여운 것 같습니다. ✧٩(ˊωˋ*)و✧