[TypeScript] Narrowing / Assertion / Generic

Dorong·2022년 12월 26일
0

TypeScript

목록 보기
10/15

  • 함수에서 union type으로 데이터를 받을 경우,
  • 타입때문에 숫자 연산 등이 작동하지 않는 등 불편한 점이 존재

    fuction plus10 (num : number | string) :void {
       console.log(num + 10)   // 실행불가
       // 왜냐면, union type은 새로운 타입을 생성하는 것과 같아서,
       // number 데이터가 들어왔다고 number타입이 되지는 않음
    }

  • 이를 해결하기 위한 방법들 또한 존재



Narrowing

  • union type이라 타입이 확정되지 않았다면, type narrowing이 필요하다

✅ typeof

  • 가장 대표적인 방법인 typeof를 활용한 if문
  • (typeof 변수)는 변수의 타입정보를 string 타입으로 반환함
    => 타입 이름을 문자열로 비교할 수 있다!!

    function typeIs(data : string | number) : void {
       if(typeof data === 'string'){
           console.log('string')
       }else if(typeof data === 'number'){
           console.log('number')
       }
    }

  • if문 써줬으면 else if, else 등 끝까지 써주는게 오류로부터 안전

✅ &&

  • 보통 null과 undefined를 거르기 위해 narrowing을 하는 경우가 잦은데,
  • 이 때 && 연산자로 간단히 이를 거를 수 있음
  • && 기준 왼쪽 조건식이 null이나 undefined라면, 오른쪽 조건식 실행 X
  • && 기준 왼쪽 조건식이 null이나 undefined가 아니라면, 오른쪽 조건식 실행 O

    function isUndf(data : number | undefined){
       if(data && typeof data === 'number'){
           console.log(data)
       }
    }


✅ in

  • 두 오브젝트를 비교하는 데 서로 배타적인 속성이 있을 때 사용 가능

    type Ipad = {pencil : boolean};
    type Iphone = {dynamicIsland : boolean};

    function infoPrinter(device : Ipad | Iphone){
       if('pencil' in device){
           console.log(device.pencil);
       }else{
           console.log(device.dynamicIsland);
       }
    }


✅ instanceof

  • 오브젝트가 비슷하다면 부모 class가 뭔지 확인해서 narrowing 가능

    let date = new Date();
    if(date instanceof Date){console.log('true')};



Assertion

  • 타입을 덮어씌우는 기능
  • 'as' 키워드로 사용가능

    function assertionFun(data : string | number) : void {
       let numebrData = data as number;   // 무조건 number타입으로 변경
       let dataType = typeof numberData;
       console.log(dataType);  // 무조건 number타입만 출력
    }

  • 편해보일 수 있으나, 남용하면 typescript의 의미도 상실되고 버그가 많이 발생할것
  • 디버깅이나 비상용으로 사용할 수 있을것
  • 차라리 narrowing을 애용하쟈!!



✅ Generic

  • 파라미터로 어떤 자료형이 들어올지 확실치 않을때, 조금 독특한 방법이 하나 더 있는데,
  • 바로 함수 호출시 자료형을 또다른 파라미터로 넣어주는 방법 => Generic
  • 함수명과 파라미터 소괄호 사이에 <>기호를 사용해 임의의 타입파라미터명 지정
  • 지정한 타입파라미터는 파라미터는 물론 리턴 타입에도 적용할 수 있음

    function returnData< MyType >(data : MyType) : MyType {
       return data;
    }

  • 타입파라미터는 함수 호출시 함수 이름과 파라미터 소괄호 사이에 <>기호로 넣어주며, 주어진 타입이 함수에 적용된다

    let str = returnData< string >('Hello');
    let num = returnData< number >(12345);
    let numArr = returnData< number[] >([1,2,3,4,5]);
    // 모든 변수에 지정한 타입변수가 잘 적용되어있음을 확인할 수 있음


  • 그런데 만약 함수 내부에서 특정 자료형에서만 쓸 수 있는 연산이 필요해서,
  • 아무 타입이나 들어와서는 안된다는 제약사항를 주고싶다면?
  • extends 키워드 사용!!

    // 예시) length 기능을 쓰고싶어서 문자열과 배열만 받고 싶다면
    function lenFunc< MyType extends string : [] >(data : MyType){
       return data.length;
    }
    let count1 = lenFunc< string >('hello');
    let count2 = lenFunc< [] >([1,2,3,4,5]);

  • 여기서 extends는 class 상속되는 것과는 다른의미!!
       => 오른쪽에 지정한 타입만 받겠다는 의미
  • 🌟 extends에는 type alias를 통한 커스텀 타입과 인터페이스도 사용가능!!





🌟 잘못된 부분에 대한 말씀은 언제나 저에게 큰 도움이 됩니다. 🌟
👍 감사합니다!! 👍

profile
🥳믓진 개발자가 되겠어요🥳

0개의 댓글