
| (OR): 유니온 타입let value: number | string | boolean = 10;
value = "hello";
value = true;
let obj: { name: string; age: number } | { skill: string } = {
name: "Alice",
age: 30,
};
obj = { skill: "JavaScript" };
let arr: number[] | string[] = [1, 2, 3];
arr = ["apple", "banana", "orange"];
// 혼합 배열: 각 요소가 숫자 또는 문자열
let mixArr: (number | string)[] = ["a", 1, "b"];
유니온 타입은 여러 타입 중 하나를 선택 가능하나, 특정 타입의 메서드 호출 시 타입 추론 불명확으로 에러 발생 가능
function printProcess(value: string | number): string | number {
return value;
}
// 반환값이 string 또는 number
const value1 = printProcess("hello, world");
const value2 = printProcess(10);
// 이 시점에서 value1과 value2의 타입이 명확하지 않아 에러 발생
console.log(value1.toUpperCase()); // 문자열 메서드
console.log(value2.toFixed(2)); // 숫자 메서드
에러 발생 이유
TypeScript는 value1과 value2가 각각 string 또는 number 중 어느 타입인지 확실하지 않으므로 메서드 호출을 허용하지 않음
타입 가드는 값의 타입을 좁혀 특정 타입임을 명시적으로 알려줌. 이를 통해 안전하게 메서드를 호출할 수 있음
타입 가드 적용 예제
function printProcess(value: string | number): string | number {
return value;
}
const value1 = printProcess("hello, world");
const value2 = printProcess(10);
// 타입 가드를 사용해 안전하게 메서드 호출
if (typeof value1 === "string") {
console.log(value1.toUpperCase()); // 문자열일 경우
}
if (typeof value2 === "number") {
console.log(value2.toFixed(2)); // 숫자일 경우
}
타입 가드로 해결된 이유
typeof value1 === "string" 조건: value1이 string 타입임이 확실하므로, toUpperCase 메서드를 안전하게 호출 가능함typeof value2 === "number" 조건: value2가 number 타입임이 확실하므로, toFixed 메서드를 안전하게 호출 가능함함수 오버로드는 같은 이름의 함수를 여러 가지 매개변수 타입과 반환 타입으로 정의하여, 함수 호출 시 정확한 타입 추론을 가능하게 함
함수 오버로드를 사용하면 코드의 가독성과 타입 안정성을 높일 수 있으나, 모든 가능한 경우의 수를 고려해야 하므로 신중한 사용 필요
함수 오버로드 예제
// 함수 오버로드 시그니처
function combine(a: number, b: number): number;
function combine(a: string, b: number): string;
function combine(a: number, b: string): string;
// 실제 구현
function combine(a: number | string, b: number | string): number | string {
if (typeof a === "number" && typeof b === "number") return a + b;
else return `${a}${b}`;
}
// 함수 호출
const result1 = combine(10, 10); // 숫자
console.log(result1.toFixed(2)); // 20.00
const result2 = combine("Hello", 10); // 문자열
console.log(result2.toUpperCase()); // HELLO10
함수 오버로드의 특징
& (AND)인터섹션 타입let value: { name: string; age: number } & { skill: string } = {
name: "Alice",
age: 30,
skill: "JavaScript",
};
🤔 왜 이렇게 사용하는가?
하나의 객체가 여러 타입의 속성을 모두 가져야 할 때 사용. 예를 들어, 아래처럼 모든 속성을 한 번에 정의할 수도 있으나, 인터섹션 타입은 타입 재사용성과 확장성을 높임
// 모든 속성을 한 번에 정의
let value2: { name: string; age: number; skill: string } = {
name: "Alice",
age: 30,
skill: "JavaScript",
};
any와 결합
any가 포함되면 결과는 항상 any로 평가let value: any & { name: string } = { name: "Alice" };
console.log(value.name); // 정상 동작
never와 결합
never가 포함되면 결과는 항상 never로 평가let value: never & { name: string };
// value는 사용할 수 없음
출처: 수코딩