영벨롭 개발 일지

[TypeScript] 타입 단언과 타입 가드 (Type Assertions & Guard) 본문

Programming Language/TypeScript

[TypeScript] 타입 단언과 타입 가드 (Type Assertions & Guard)

영벨롭 2024. 1. 16. 19:02

📌 타입 단언 Type Assertions

 타입 단언은 타입스크립트가 타입 추론을 통해 판단할 수 있는 타입의 범주를 넘는 경우, 더 이상 추론하지 않도록 지시하는 것입니다. 

 즉, 개발자가 타입스크립트에게 '이 타입이 맞아!'라고 알려주는 것입니다.  

 런타임에는 영향을 미치지 않고, 오직 컴파일 과정에서 사용됩니다. 

 타입 단언은 강제 형변환과는 다른 개념입니다. 단지 컴파일러에게 타입을 주장할 뿐, 실제로 데이터 자료를 변환시키는 것은 아닙니다. 

 

 타입 단언을 하는 방법에는 as 문법꺽쇠<>문법이 있습니다. 

 다만, 꺽쇠<> 문은 태그 엘리멘트와 헷갈릴 수 있어, TSX 파일에서는 사용이 불가능합니다. 

let val: any = 1.23;
(val as number).toFixed(2); // as 문법
(<number>val).toFixed(2); // <> 문법

 

✅  타입 단언의 단점

 하지만 타입 단언이 계속 반복되게 되면 비효율적인 코드가 될 수 있습니다. 때문에 해당 변수가 unknown 타입일 경우에만 사용하는 것을 권장합니다. 

// 타입 단언을 여러 번 사용하게 됨
function func(val: string | number, isNumber: boolean) {
  if (isNumber) {
    (val as number).toFixed(2);
    isNaN(val as number);
  } else {
    (val as string).split(" ");
    (val as string).toUpperCase();
    (val as string).length;
  }
}

📌 타입 가드 Type Guard

 타입 가드는 조건문 안에서 타입 범위를 한정시켜줄 수 있는 방법입니다. 

 즉, 타입스크립트가 추론 가능한 특정 범위(scope)에서 타입을 보장할 수 있는 방법입니다. 

 타입 가드를 사용하면 코드가 훨씬 깔끔해지기 때문에 위 타입 단언의 단점을 보완할 수 있습니다. 

 

 타입 가드를 하는 방법에는 다음이 있습니다. 

1. NAME is TYPE 형태의 타입 술부(Predicate)를 반환 타입으로 명시한 함수
2. typeof - 일반 타입 가드
3. instanceof - 클래스 타입 가드
4. in - 객체 속성 가드
5. Array.isArray() - 배열 타입 가드

 

✅  타입 가드 - 타입 술부

 함수의 반환 타입으로 NAME is TYPE 형태를 명시하여 타입 가드를 합니다. 

function isNumber(val: string | number): val is number {
  return typeof val === "number";
}

function func(val: string | number) {
  if (isNumber(val)) {
    val.toFixed(2);
    isNaN(val);
  } else {
    val.split(" ");
    val.toUpperCase();
    val.length;
  }
}

 

✅  일반 타입 가드 typeof 

 typeof 를 사용하여 타입 가드를 할 수 있습니다.

 이때 주의해야 할 점은 number, string, boolean, symbol 타입만 타입 가드로 인식할 수 있습니다.

 커스텀 타입이나 인터페이스와 같이 복잡한 타입에는 사용이 불가합니다. 

function func(val: string | number) {
  if (typeof val === "number") {
    val.toFixed(2);
  } else {
    val.toUpperCase();
  }
}

 

✅  클래스 타입 가드 instanceof

 instanceof 를 사용하여 객체가 특정한 클래스에 속하는지 확인할 수 있습니다. 

class Cat {
  meow() {}
}
class Dog {
  woof() {}
}
function sounds(ani: Cat | Dog) {
  if (ani instanceof Cat) {
    ani.meow()
  } else {
    ani.woof()
  }
}

 

✅  객체 프로퍼티 타입 가드 in

 in 연산자를 통해 객체 내부에 특정 프로퍼티가 존재하는지를 확인할 수 있습니다.

 이때 주의해야할 점은 in 연산자의 우변 객체는 any 타입이어야 합니다.

function func(val: any) {
  if ("toFixed" in val) {
    val.toFixed(2);
  } else if ("split" in val) {
    val.split(" ")
  }
}

 

✅  배열 타입 가드 Array.isArray()

function numOrArr(val: number | number[]) {
  if (Array.isArray(val)) {
    console.log(val.length);
  } else {
    console.log(val.toFixed(2));
  }
}

 

 

 


📚 참고

https://inpa.tistory.com/entry/TS-%F0%9F%93%98-%ED%83%80%EC%9E%85-%EC%B6%94%EB%A1%A0-%ED%83%80%EC%9E%85-%ED%98%B8%ED%99%98-%ED%83%80%EC%9E%85-%EB%8B%A8%EC%96%B8-%ED%83%80%EC%9E%85-%EA%B0%80%EB%93%9C-%F0%9F%92%AF-%EC%B4%9D%EC%A0%95%EB%A6%AC#%ED%83%80%EC%9E%85_%EB%8B%A8%EC%96%B8_assertions

 

https://heropy.blog/2020/01/27/typescript/

반응형