ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 타입스크립트의 is 키워드에 대해 알아보고 활용해보자
    기타 2023. 11. 29. 22:08

    typescript의 Is 키워드는 type guard를 위해 사용할 수 있습니다.

    함수가 boolean을 반환할때 함수의 argument 타입의 추론을 도와줄 수 있는데요, 쉬운 예시부터 차근차근 알아가보겠습니다.

     

    쉬운 예시

    검색을 해보면 아래와 같은 예시를 가장 흔하게 볼 수 있습니다.

    const isNumber = (x: any): x is number => {
      return typeof x === 'number';
    }
    

     

    여기서 is keyword가 없으면 어떻게 될까요?

     

    const isNumber = (x: any) => {
      return typeof x === "number";
    }
    
    const doSomething = (x: any) => {
      if (isNumber(x)) {
        return x + 1;
      }
    

    doSomething함수에서 b의 타입은 어떻게 추론될까요?

    우리는 isNumber함수를 통과하면 x가 number type이라는것을 알 수 있지만, typescript는 x를 any로 추론을 합니다.

     

    그렇다면 is keyword가 isNumber함수에 있다면 어떻게 될까요?

    const isNumber = (x: any): x is number => {
      return typeof x === "number";
    }
    
    const doSomething = (x: any) => {
      if (isNumber(x)) {
        return x + 1;
      }
    };
    

     

     

    number type으로 추론을 잘 하는것을 볼 수 있습니다.

    즉 맨처음에 이야기했던것처럼 isNubmer함수의 경우 boolean을 반환하는 함수입니다.

    그러므로 is keyword를 사용해서 타입을 좁혀줄 수 있는데요, is keyword는 함수가 true일때의 argument를 정의해줄 수 있습니다.

    즉 isNumber의 반환값이 true라면, x is number(인자x는 number야). 라고 알려주는거죠. 이렇게 보면 is가 딱 영어로 함수를 설명하는것과 비슷하지 않나요?

     

     

    활용

    그럼 어떻게 활용할 수 있을까요?

    우리는 부족한 js내장함수들을 보충하거나 여러 이유로 lodash와 같은 라이브러리를 많이 사용합니다.

    이때 타입가드가 되지 않는 문제가 종종 있는데요, isUndefined와 같은 함수를 예로 들어보겠습니다.

    구현체를 보면 코드는 굉장히 간단한데요,

    사실 if(value === undefined) 를 사용하는곳에서 계속 쓰기 싫어서 사용한 isUndefined함수이지만 막상 사용할때는 타입 유추가 되지 않아서 as 키워드를 통해 타입단언을 계속 해줘야하죠.

    const isUndefined = (x) => {
      return x === undefined;
    }
    const doSomething = (x?: number ) => {
      if (!isUndefined(x)) {
        return (x as number) + 1 // 단언을 해주지 않으면 타입오류가 난다.
      }
    };

     

     

     

    이걸 is keyword를 통해 타입 추론이 잘 되도록 고쳐볼까요?

    우선 isUndefined함수의 인자타입부터 고쳐주도록 하겠습니다.

    어느 타입도 들어올 수 있어야 하니까 제네릭으로 받으면 좋을것 같네요.

    const isUndefined = <T>(x: T) => {
      return x === undefined;
    }
    

    이제 is keyword를 통해 타입가드를 해보겠습니다.

    const isUndefined = <T>(x: T): x is undefined => {
      return x === undefined;
    }

    이렇게 하면 간단하게 될 줄 알았는데 오류가 납니다.

    저는 예측을 도와주는 타입은 파라미터의 타입으로 할당되어야 한다라고 오류를 생각했습니다.

    즉 파라미터의 타입을 제네릭으로 받고 있기 때문에 undefined를 할당할 수 없는것 같네요.

    그럼 어떻게 할 수 있을까요?'

     

     

    const isUndefined = <T>(x: T): x is T extends undefined ? T : never => {
      return x === undefined;
    };
    

    이런식으로 작성할 수 있을것 같은데요,

    isUndefined의 인자인 x가 undefined일 때

    1. isUndefined함수는 true를 반환하게됩니다.
    2. 이에 따라 is keyword를 통해 x를 추론합니다.
      1. T(undefined)가 extends undefined === true입니다.
      2. 따라서 x는 never가 아닌 T(undefined)로 추론이됩니다.
      3. 즉 isUndefined함수의 인자가 undefined라면 true이기 때문에 x는 T(undefined)로 추론을 하겠죠

    이제 isUndefined함수를 사용해볼까요??

    const isUndefined = <T>(x: T): x is T extends undefined ? T : never => {
      return x === undefined;
    };
    
    const doSomething = (x?: number) => {
      if (!isUndefined(x)) {
        return x + 1;
      } else {
        console.log(x);
      }
    };
    

    이때 if문안의 x와 else의 x를 보면 추론이 잘 되는것을 볼 수 있습니다!

    이제 타입단언없이 isUndefined함수를 잘 사용할 수 있을것 같네요.

    이처럼 is keyword를 적절히 사용한다면 as keyword를 통한 타입단언을 줄일 수 있지 않을까 생각합니다

    댓글

Designed by Tistory.