본문 바로가기

TypeScript

🧩 Props에 타입 주는 법 완전 정리 (React + TypeScript)

들어가면서

 

React 컴포넌트를 만들 때 가장 기본이자 중요한 부분은 Props를 제대로 타입 지정하는 것이다.

이전 포스팅에 이어지는 내용으로,
이번 포스팅에서는 실무에서도 자주 쓰이는 패턴을 중심으로, children, optional, default 값 처리까지 깔끔하게 정리해보겠다.

 

 

✅ 1. 기본적인 Props 타입 지정

type ButtonProps = {
  label: string;
  onClick: () => void;
};

function Button({ label, onClick }: ButtonProps) {
  return <button onClick={onClick}>{label}</button>;
}

 

  • type 또는 interface로 Props 정의 가능
  • 함수형 컴포넌트에 인자로 구조분해하여 사용

 

✅ 2. Optional Props (선택적으로 받을 수 있는 경우)

type CardProps = {
  title: string;
  subtitle?: string; // optional
};

function Card({ title, subtitle }: CardProps) {
  return (
    <div>
      <h2>{title}</h2>
      {subtitle && <p>{subtitle}</p>}
    </div>
  );
}

 

  • ?로 표시하면 필수 prop 아님
  • 렌더링 조건 분기 시 && 연산자 자주 사용

 

 

✅ 3. Default Props (기본값 지정)

type BadgeProps = {
  text: string;
  color?: string;
};

function Badge({ text, color = 'gray' }: BadgeProps) {
  return <span style={{ backgroundColor: color }}>{text}</span>;
}
  • 기본값은 구조분해 시 지정하는 것이 가장 깔끔
  • 기존 방식인 Component.defaultProps는 함수형 컴포넌트에선 비권장

 

✅ 4. children Props 타입 지정

type LayoutProps = {
  children: React.ReactNode;
};

function Layout({ children }: LayoutProps) {
  return <div className="layout">{children}</div>;
}

 

  • children은 명시적으로 React.ReactNode 또는 JSX.Element로 선언
  • 여러 개의 JSX를 자식으로 받을 수 있어야 하므로 대부분 React.ReactNode를 사용

 

 

✅ 5. Props 타입 정의 방법: type vs interface

// interface 버전
interface ModalProps {
  open: boolean;
  onClose: () => void;
}

// type 버전
type ModalProps = {
  open: boolean;
  onClose: () => void;
};

 

  • 대부분의 경우 type과 interface는 동일하게 사용 가능
  • 확장성이 필요하거나 상속 받을 경우엔 interface
  • 유니언/인터섹션 타입 조합이 필요하면 type 추천

 

 

 

✅ 6. 유니언 타입으로 prop 제한하기 (리터럴 타입)

type AlertProps = {
  type: 'success' | 'error' | 'info';
};

function Alert({ type }: AlertProps) {
  return <div className={`alert ${type}`}>{type} 메시지입니다.</div>;
}
  • 잘못된 문자열 입력 방지
  • setType('loading') → 에러 발생! 👍

 

✅ 7. HTML 기본 태그 속성과 병행 (extends 활용)

type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
  label: string;
};

function Input({ label, ...props }: InputProps) {
  return (
    <label>
      {label}
      <input {...props} />
    </label>
  );
}

 

  • 기본 HTML 속성도 그대로 쓸 수 있게 만들기
  • 실무에서는 Button, Input, Textarea 등의 공통 컴포넌트 제작에 자주 사용

 

✅ 8. 컴포넌트 재사용을 위한 Generic Props

type SelectProps<T> = {
  options: T[];
  getLabel: (item: T) => string;
};

function Select<T>({ options, getLabel }: SelectProps<T>) {
  return (
    <select>
      {options.map((item, i) => (
        <option key={i}>{getLabel(item)}</option>
      ))}
    </select>
  );
}

 

  • 고급 패턴이지만 매우 강력함!
  • 어떤 데이터든 label만 뽑을 수 있다면 재사용 가능

 

 

💬 마무리하며

  • Props는 컴포넌트 설계의 핵심
  • 명확한 타입 선언은 협업/리팩토링/오류 방지에 큰 도움
  • 기본 타입에서 시작해서 점점 유연하게 확장하는 방식이 안전하고 실무에 적합