● 타입가드
class Car {
drive(){
console.log('Driving...');
}
}
class Truck {
drive(){
console.log('Drivig a Truck...')
}
loadCargo(amount: number){
console.log('Loading cargo..' + amount);
}
}
위와 같이 2개의 클래스가 있다고 했을 때, 어떠한 함수가 있다고 정의해보자.
type Vehicle = Car | Truck;
const v1 = new Car();
const v2 = new Truck();
// 에러의 상황
function useVehicle(vehicle: Vehicle){
vehicle.drive();
vehicle.loadCargo(1000);
}
그럼 useVehicle의 상황은 에러가 나게 될 것이다. 왜냐하면 loadCargo라는 메서드는 Truck에만 존재하기 때문이다. 따라서 이런 타입들을 막아주어야하는데, 이런 것들을 '타입 가드'라고 한다.
그럼 어떻게 타입가드를 해주어야할까?
type Vehicle = Car | Truck;
const v1 = new Car();
const v2 = new Truck();
function useVehicle(vehicle: Vehicle){
vehicle.drive();
// 'in'을 통해서 vehicle에 프로퍼티가 있는지 확인한다.
if ('loadCargo' in vehicle){
vehicle.loadCargo(1000);
}
}
위와 같이 프로퍼티가 있는지 확인하고, 메서드를 호출한다.
아니면
type Vehicle = Car | Truck;
const v1 = new Car();
const v2 = new Truck();
function useVehicle(vehicle: Vehicle){
vehicle.drive();
// 객체가 Truck의 instance인지 확인한다.
if (vehicle instanceof Truck){
vehicle.loadCargo(1000);
}
}
아니면 instanceof 를 통해 확인 후 함수를 호출한다.
따라서 타입가드는 3가지 방법이 있다.
- 타입 확인하기 (string 인지 , number인지 등등.. )
- 하지만 그 프로퍼티가 없을 경우에는 타입을 확인할수 없다. 예를 들어, if (vehicle.drive: Function) 이런식으로 확인할 수 없기 때문에, 'in' 이라는 것을 통해 확인한다.
- 클래스에서 생성된 객체라면 instanceof로도 확인 할 수 있다.
하지만 객체가 가진 타입의 이름에 구별해서 if나 switch구문에 따라 다른 실행을 하게 할 수도 있다.
interface Bird {
type: "bird";
flyingSpeed: number;
}
interface Horse {
type: "horse";
runningSpeed: number;
}
type Animal = Bird | Horse;
function moveAnimal(animal: Animal) {
let speed;
switch (animal.type) {
case "bird":
speed = animal.flyingSpeed;
break;
case "horse":
speed = animal.runningSpeed;
break;
}
console.log("Moving at speed:" + speed);
}
moveAnimal({ type: "bird", flyingSpeed: 10 });
두 개의 방식을 때에따라 적절히 사용하면 좋을 것 같다.