React + Typescript 제네릭 사용하기

jungGone·2021년 6월 12일
6

React + Typescript

목록 보기
3/3
post-thumbnail

✅ 제네릭 알아보기.

타입스크립트를 사용해 개발할때 제네릭은 매우 유용하게 사용되는 기능중 하나일 것 입니다.

const 현수 = {
  name: "현수",
  age: 28
}

const 민수 = {
  name: "민수",
  age: 27
  friend: [
    {
      name: "철수",
      age: 27	
    }
  ]
}

function helloUser(user) {
  return `안녕하세요 ${user.name}님!`
}

console.log(helloUser(현수))
console.log(helloUser(민수))

위 예시를 자바스크립트에서 사용할때는 아무런 문제가 되지않습니다.
하지만 타입스크립트에서 사용한다면 어떻게 될까요?
현수객체와 민수객체의 구조가 달라 타입에러가 발생할 것 입니다.

type 현수타입 = {
  name: string
  age: number
}

type 민수타입 = {
  name: string
  age: number
  friend: {
    name: string
    age: number
  }[]
}

const 현수: 현수타입 = {
  name: "현수",
  age: 28
}

const 민수: 민수타입 = {
  name: "민수",
  age: 27
  friend: [
    {
      name: "철수",
      age: 27	
    }
  ]
}

// 유니온 타입을 사용해 줄 수도 있을것입니다.
function helloUser(user: 현수타입 | 민수타입): string {
  return `안녕하세요 ${user.name}님!`
}

console.log(helloUser(현수))
console.log(helloUser(민수))

위 처럼 유니온타입등 해결방법은 많지만 이렇게 파라미터의 타입이 여러가지이거나 그때그때 다른타입을 받지만 같은로직이 수행가능할때는 제네릭을 사용해 주는것이 좋다고 생각 됩니다.

// 제네릭 타입 지정
function helloUser<T>(user: T): string {
  return `안녕하세요 ${user.name}님!`
}

console.log(helloUser<현수타입>(현수))
console.log(helloUser<민수타입>(민수))

위 처럼 제네릭을 사용해 함수를 정의할때 타입을 지정해 줄 수 있습니다.
리액트에서 재사용성이 높은 컴포넌트를 작성할때 props의 값이 정적이지 않다면 제네릭을 사용해주는 것도 좋은 방법이라고 생각합니다.

✅ 리액트 컴포넌트 props제네릭으로 정의해 주기.

테이블 컴포넌트

interface TableType<T> {
  field: { title: string; key: keyof T }[];
  rows: T[];
}

function Table<T>(props: TableType<T>): React.ReactElement {
  return (
    <div>
      <div 
        style={{
          display: "flex",
          justifyContent: "space-around",
          border: "1px solid #333",
          borderBottom: 0,
          background: "#ddd"
        }}
      >
        {props.field.map((head) => (
          <p>{head.title}</p>
        ))}
      </div>
      <div
        style={{
          border: "1px solid #333"
        }}
      >
        {props.rows.map((item) => (
          <div 
            style={{
              display: "flex",
              justifyContent: "space-around",
              borderBottom: props.rows.length !== i + 1 ? "1px solid #333" : "0"
            }}
          >
            {props.field.map((field) => (
              <p>{item[field.key]}</p>
            ))}
          </div>
        ))}
      </div>
    </div>
  );
}

예제를 만들어두고 글 작성한게 아니라.. 급하게 만들어 봤습니다.
쨋든 테이블 컴포넌트에 제네릭을 사용해서 작성해 봤어요 허접한 예제..

부모컴포넌트

export default function App() {
  type CurrentUserType = {
    name: string;
    age: number;
    
  };
  const currUsers: CurrentUserType[] = [
    {
      name: "현수",
      age: 28
    },
    {
      name: "민수",
      age: 25
    },
    {
      name: "철수",
      age: 26
    }
  ];

  return (
    <div className="App">
      //이렇게 컴포넌트에도 제네릭 타입을 넘겨 줄 수 있습니다~!
      <Table<CurrentUserType>
        field={[
          { title: "이름", key: "name" },
          { title: "나이", key: "age" }
        ]}
        rows={currUsers}
      />
    </div>
  );
}

카페에서 글작성하고 있는데 에어컨아래에서 쓰니까 너무 추워서 언능끝내야겠다는
무의식이 생겨 갈수록 대충쓴거 같네요^_^
제네릭에대한 기본적인 사용법과 컴포넌트에 제네릭을 넘기는 방법을 기초적으로 알아보았습니다! 잘못된 점이나 궁금하신부분이 있으시다면 연락주세용 ^~^

profile
프런트개발 좋아~

2개의 댓글

comment-user-thumbnail
2023년 5월 25일

vs code 상에서는 자식컴포넌트에서 {item[field.key]} 부분에서 에러가 발생하는데 왜 그런건가요?

답글 달기
comment-user-thumbnail
2023년 8월 14일

If you have an affinity for the convenience of one-click play functionality and a plethora of high-definition content consolidated within a singular application, your search concludes here with the introduction of HDO Box Download. Offering a comparable experience to the Filelinked app, Applinked emerges as an alternative option. Upon establishing your personalized store, you will receive a unique Applinked Codes paired with a PIN for access.

답글 달기