ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 타입스크립트에서 기존 코드로부터 타입을 가져오는 법 ReturnType, ComponentProps
    TypeScript 2024. 9. 18. 19:22

    타입스크립트를 잘 사용하기 위한 여러 유틸 타입이 있다.

     

    그중에서도 이미 잘 사용중이던 함수를 사용한다면, ReturnType을 통해서 해당 함수의 반환값 타입을 쉽게 얻을 수 있다.

     

    ReturnType

     

    function getUser() {
      return {
        name: "Alice",
        age: 30,
      };
    }

     

    이런 함수가 있을 때, 이 함수의 리턴값 타입을 재사용하고자 하는 경우를 생각해보자.

    interface getUserReturnValue {
      name: string;
      age: number;
    }

     

    이렇게 타입을 직접 작성할 수도 있지만, 만약 getUser 함수의 리턴값이 바뀌는 작업이 일어나면 타입도 직접 바꿔줘야 한다.

    그리고 사람이 작성하는 코드이기에, 실수가 일어나기 더 쉬워보인다.

     

    때문에 다음과 같이 작성하는 방법을 사용할 수 있다.

    type User = ReturnType<typeof getUser>;

     

    ReturnType 유틸 타입이 자동으로 함수의 리턴값을 추론해주므로, 아주 편리하게 타입을 가져와 사용할 수 있다.

     

    ComponentProps

     

    그리고, 비슷한 케이스로 React를 사용하면, Props에 타입을 작성하게 되는데 이 Props는 때때로 여러번 사용될 경우가 있다.

     

    맨 처음 컴포넌트를 작성하며 Props의 타입을 작성하는 경우는 다음과 같은 예제로 표현할 수 있다.

    type ButtonProps = {
      label: string;
      onClick: () => void;
    };
    
    const Button = (props: ButtonProps) => {
      return <button onClick={props.onClick}>{props.label}</button>;
    };

     

    해당 버튼에 대한 Props를 작성해준다.

     

    그런데 만약 같은 Props를 전달받는 OutlintedButton 컴포넌트가 있다면, 어떻게 하는 것이 좋을까?

     

    type OutlintedButtonProps = {
      label: string;
      onClick: () => void;
    };
    
    const OutlintedButton  = (props: ButtonProps) => {
      return <button 
                 style={{ background: "#000", color: "#fff" }} 
                 onClick={props.onClick}
             >{props.label}</button>;
    };

     

    같은 타입을  두 번 선언하는 것이 좋을까?

     

    이런 경우에는 ComponentProps를 사용하여 기존의 Button 컴포넌트로부터 Props의 타입을 가져올 수 있다.

     

    import { ComponentProps } from "react";
    import Button from "./Button";
    
    
    const OutlintedButton  = (props: ComponentProps<typeof Button>) => {
      return <button 
                 style={{ background: "#000", color: "#fff" }} 
                 onClick={props.onClick}
             >{props.label}</button>;
    };

     

     

    이렇게 하면 중복으로 Props를 선언하는 일 없이 동일한 타입을 사용할 수 있다.

     

    👻 하지만, ComponentProps는 정말 유용할까?

    그러나 컴포넌트를 생성할 때 Props에 대한 타입은 자연스럽게 만들게 된다.

     

    그렇다면, ComponentProps를 사용하는 일 없이 export한 타입을 import하여 사용하면 그만이지 않을까?

     

    거기에 컴포넌트에 추가 기능이 생기면서 Props가 추가되기라도 하면, 기존에 선언한 타입에 추가로 타입을 extends를 하여 확장하는 것이 더 바람직해 보인다.

    (ComponentProps로 가져온 타입에 extends하는 것 보다 가독성이 나아  보기 깔끔할지도 모른다...)

     

     

    때문에, 완전히 동기화된 컴포넌트에서는 ComponentProps가 유용할 수 있지만, 대다수의 경우에은 선언한 타입을 import하는 것으로 충분하지 않을까 하는 생각이 들었다.

     

    🎶 ComponentProps는 특수한 상황에서 효과적이고, 특히 외부에서 전달된 컴포넌트를 사용하는 경우가 제일 좋은 사용처 같다.

    • 다른 사람이 작성한 라이브러리 컴포넌트를 불러와 사용하는 경우 (사실 이 경우에도, 해당 라이브러리 내부에 type을 export하는 경우가 대부분인듯)

     

    ✨ ReturnType역시 이미 존재하는 함수에서 타입을 가져오기 때문에, ComponentProps처럼 사용처가 애매한 것 같다.

    그래도, 함수의 경우에는 자동으로 리턴 타입을 추론해주는 경우가 많기에 따로 리턴 타입을 작성하지 않는 경우가 있고, 이 경우에는 유용하게 사용될 수 있을 것 같다.

     

     

    https://www.totaltypescript.com/react-component-props-type-helper

     

    ComponentProps: React's Most Useful Type Helper

    Discover the power of ComponentProps in React and TypeScript.

    www.totaltypescript.com

    https://www.typescriptlang.org/ko/docs/handbook/utility-types.html#returntypetype

     

    Documentation - Utility Types

    Types which are globally included in TypeScript

    www.typescriptlang.org

     

Designed by Tistory.