안녕하세요, TypeScript의 중요한 개념 중 하나인 타입 좁히기(Narrowing)에 대해 깊이 알아보겠습니다. TypeScript의 타입 좁히기는 조건문 등을 통해 변수의 타입을 더 구체적으로 좁혀가는 과정으로, 코드의 안전성과 가독성을 높이는 데 큰 도움을 줍니다. 이번 글에서는 타입 좁히기의 정의와 다양한 사용 사례, 실무 팁까지 차근차근 살펴보겠습니다.
TypeScript에서 타입 좁히기(Narrowing)란 코드의 실행 흐름을 따라 변수의 타입을 더 구체적으로 추론하거나 명시하는 과정을 의미합니다. TypeScript는 변수의 초기 타입이 string | number
와 같은 유니언 타입일 때, 조건문이나 타입 검사 등을 통해 해당 타입을 점점 구체화할 수 있습니다.
function printLength(value: string | number): void {
if (typeof value === 'string') {
// value는 string 타입으로 좁혀짐
console.log(`문자열의 길이: ${value.length}`);
} else {
// value는 number 타입으로 좁혀짐
console.log(`숫자의 자릿수: ${value.toString().length}`);
}
}
printLength('Hello'); // 문자열의 길이: 5
printLength(12345); // 숫자의 자릿수: 5
위 예제에서 typeof
를 사용하여 value
의 타입을 검사한 후, 각 조건문 내부에서 value
는 해당 타입으로 좁혀집니다. 이를 통해 안전하게 타입에 맞는 작업을 수행할 수 있습니다.
typeof
검사typeof
연산자를 사용하면 변수의 기본 타입을 확인할 수 있습니다. 이는 string
, number
, boolean
, object
, undefined
, function
등을 검사하는 데 사용됩니다.
function processValue(value: string | number | boolean): void {
if (typeof value === 'string') {
console.log(`문자열 처리: ${value.toUpperCase()}`);
} else if (typeof value === 'number') {
console.log(`숫자 처리: ${value * 2}`);
} else {
console.log(`불리언 처리: ${value ? '참' : '거짓'}`);
}
}
instanceof
검사instanceof
연산자를 사용하면 객체가 특정 클래스의 인스턴스인지 확인할 수 있습니다. 이를 통해 객체의 타입을 좁힐 수 있습니다.
class Dog {
bark() {
console.log('멍멍!');
}
}
class Cat {
meow() {
console.log('야옹!');
}
}
function makeSound(animal: Dog | Cat): void {
if (animal instanceof Dog) {
animal.bark();
} else {
animal.meow();
}
}
사용자 정의 타입 가드는 함수 내부에서 특정 조건에 따라 타입을 좁히는 데 사용됩니다. 반환 타입을 param is Type
형식으로 지정하여 타입스크립트에 타입 좁히기를 명시합니다.
function isString(value: unknown): value is string {
return typeof value === 'string';
}
function logValue(value: string | number): void {
if (isString(value)) {
console.log(`문자열: ${value.toUpperCase()}`);
} else {
console.log(`숫자: ${value * 2}`);
}
}
in
연산자in
연산자를 사용하면 객체에 특정 속성이 존재하는지 확인하여 타입을 좁힐 수 있습니다.
interface Car {
drive(): void;
}
interface Boat {
sail(): void;
}
function operate(vehicle: Car | Boat): void {
if ('drive' in vehicle) {
vehicle.drive();
} else {
vehicle.sail();
}
}
strictNullChecks
옵션이 활성화된 경우, TypeScript는 null
과 undefined
를 명시적으로 처리해야 합니다.
function greet(name: string | null): void {
if (name !== null) {
console.log(`안녕하세요, ${name}!`);
} else {
console.log('안녕하세요!');
}
}
타입 좁히기와 타입 단언(Type Assertion)은 유사한 목적을 가질 수 있지만, 동작 방식과 의도가 다릅니다.
const input = document.getElementById('user-input') as HTMLInputElement;
input.value = 'Hello'; // 타입 단언
타입 단언은 잘못된 사용 시 런타임 오류를 초래할 수 있으므로, 가능한 타입 좁히기를 우선적으로 사용하는 것이 좋습니다.
string | number
와 같은 유니언 타입을 다룰 때 타입 좁히기를 사용하면 코드가 더 안전하고 명확해집니다.in
연산자와 사용자 정의 타입 가드를 활용하면 오류를 줄일 수 있습니다.TypeScript의 타입 좁히기는 타입 안전성과 코드 가독성을 높이는 데 매우 유용한 도구입니다.
typeof
, instanceof
, in
연산자와 사용자 정의 타입 가드를 활용해 유연하고 안전한 코드를 작성할 수 있습니다.타입 좁히기를 적극적으로 활용하여 더욱 안정적이고 유지보수하기 쉬운 TypeScript 코드를 작성해 보세요! 🙌