타입스크립트에서 타입 가드는 런타임에 변수의 타입을 확인하고, 이를 통해 타입스크립트가 해당 변수의 타입을 특정 블록 안에서 더 정확하게 추론할 수 있도록 돕는 방법이다.
타입 가드를 잘 활용하면 코드의 타입 안전성을 높이고, 가독성과 유지보수성을 향상시킬 수 있다.
때문에 타입가드를 잘 사용하는 것은 타입스크립트에서 중요하다.
타입가드에 어떤 방법들이 있는지 확인하고, 어떤 방법을 사용하는 것이 좋을지 알아보았다.
1. 타입 단언(`as` 키워드) - 추천하지 않음
타입 단언은 변수의 타입을 명시적으로 지정하는 방법이다.
let str: string | undefined;
str = "Hi" as string;
그러나 런타임에 아무런 검사를 하지 않기 때문에 잘못된 단언으로 인해 런타임 에러를 유발할 수 있다.
따라서 가능한 한 사용을 피하는 것이 좋다.
function processValue(value: string | number) {
if ((value as string).toUpperCase) {
// Here we are asserting that value is a string
console.log(`String value in uppercase: ${(value as string).toUpperCase()}`);
} else {
// Here we are asserting that value is a number
console.log(`Number value: ${value as number}`);
}
}
processValue("hello");
processValue(100);
위 예제에서 `value as string` 또는 `value as number`로 타입을 단언하고 있다.
그러나, 이 경우는 개발자가 모든 타입에 대한 확신을 가지지 않는 경우 타입 안정성이 보장되지 않을 가능성이 있다.
때문에 이 방법은 타입 안전성을 보장하지 않기 때문에 추천되지 않는다.
2. `typeof` 타입 가드 - 원시 타입에 유용
`typeof` 연산자는 원시 타입(primitive type)을 확인할 때 사용된다.
주로 문자열, 숫자, 불리언 등 원시 타입을 구분할 때 유용하다.
function printValue(value: string | number) {
if (typeof value === 'string') {
// value is treated as a string here
console.log(`String value: ${value}`);
} else {
// value is treated as a number here
console.log(`Number value: ${value}`);
}
}
printValue("Hello");
printValue(42);
`typeof` 연산자는 타입을 정확히 구분할 수 있어 원시 타입을 다룰 때 유용하지만, 객체 타입에는 사용할 수 없다.
그리고 배열은 object 타입으로 판단되기에 Array.isArray() 같은 메서드를 활용해야 하는 등 추가로 고려해야할 사항이 많다.
3. `instanceof` 타입 가드 - 클래스 인스턴스에 유용
`instanceof` 연산자는 객체가 특정 클래스의 인스턴스인지 확인할 때 사용된다.
👻 instanceof는 참고로 타입스크립트 문법이 아닌, 자바스크립트 문법이다. mdn 문서
클래스 기반 객체를 구분하는 데 유용하다.
class Dog {
bark() {
console.log('Woof!');
}
}
class Cat {
meow() {
console.log('Meow!');
}
}
function makeSound(animal: Dog | Cat) {
if (animal instanceof Dog) {
// animal is treated as Dog here
animal.bark();
} else {
// animal is treated as Cat here
animal.meow();
}
}
const dog = new Dog();
const cat = new Cat();
makeSound(dog);
makeSound(cat);
`instanceof` 연산자는 클래스 기반 객체의 타입을 확인할 때 유용하지만, 인터페이스나 타입 별칭으로 정의된 타입에는 사용할 수 없다.
4. 커스텀 타입 가드 함수 - 가장 유연하고 강력 ✨
가장 추천하는 방법은 커스텀 타입 가드 함수를 사용하는 것이다.
이 방법은 특정 타입을 정의하고 확인할 수 있는 가장 유연하고 강력한 방법이다.
interface Fish {
swim(): void;
}
interface Bird {
fly(): void;
}
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
function move(pet: Fish | Bird) {
if (isFish(pet)) {
// pet is treated as Fish here
pet.swim();
} else {
// pet is treated as Bird here
pet.fly();
}
}
const fish: Fish = {
swim() {
console.log('Fish is swimming');
}
};
const bird: Bird = {
fly() {
console.log('Bird is flying');
}
};
move(fish);
move(bird);
위 예제에서 `isFish` 함수는 커스텀 타입 가드 함수로, `pet`이 `Fish` 타입인지 확인한다.
이 방법은 타입스크립트가 타입을 정확하게 추론할 수 있도록 도와주며, 코드의 가독성과 유지보수성을 크게 향상시킨다.
또한 타입가드는 배열의 .filter 고차함수와 함께 사용될 수 있다.
const strArr: (string | undefined)[] = ['hi', 'bye'];
function isString(item: unknown): item is string {
return typeof item === 'string';
}
const checkedStrArr = strArr.filter(isString); // string[]
이렇게 순수한 string 배열을 얻을 수도 있다.
👻 타입스크립트에서 타입 가드를 사용하면 코드의 타입 안전성을 높일 수 있다.
- `as` 키워드를 사용한 타입 단언은 피하는 것이 좋다.
- `typeof`와 `instanceof` 연산자는 원시 타입과 클래스 인스턴스를 구분할 때 유용하다. (제한적인 사용법)
- 가장 추천하는 방법은 커스텀 타입 가드 함수를 사용하는 것으로, 이를 통해 타입스크립트가 타입을 정확하게 추론하고, 더 안전한 코드를 작성할 수 있다.
'TypeScript' 카테고리의 다른 글
[typescript] Record를 사용하여 객체 Key 타입 설정하기 🍎 (0) | 2024.11.01 |
---|---|
타입스크립트에서 기존 코드로부터 타입을 가져오는 법 ReturnType, ComponentProps (0) | 2024.09.18 |
TypeScript에서 enum 사용하기: const enum vs as const 객체 (0) | 2024.04.01 |
TypeScript에서 객체 타입 체크하는 방법: in 키워드 활용하기 (0) | 2024.03.16 |
unknown과 any 차이점 알아보기 (0) | 2023.08.19 |