Typescript에서 Generic 제대로 사용하기

WooJu·2024년 3월 24일

개발

목록 보기
2/12

왜?

typescript로 프로젝트를 진행하던 중 특정 기능에서 반복적으로 사용되는 컴포넌트가 있길래 공용컴포넌트로 만들었다. 그런데 특정 타입만 props로 전달받을 수 있게 해뒀더니 확장성에서 다소 불편함을 느꼈고 공용컴포넌트라고 하기엔 많이 제한적이다 라고 생각이 들던중 generic을 알게되어 한번 공부해서 사용해봤다.

Generic이란?

단일 타입이 아닌 여러 타입을 받을 수 있어서 재사용가능한 컴포넌트를 만들기에 용이하다.(typescript공식문서)


공식문서에서는 위와 같이만 나와있기에 사실 어떻게 써야하고 뭐가 좋은지 명확히 와닿지 않았다. 그래서 실제로 내가 써보고 뭐가 좋은지 어떨때 써야하는지에 대해서 기록해보려 한다.

Generic사용방법

아래 코드를 해석한다면 Login컴포넌트에 props로 그 어떠한것도 넘겨도 된다는 의미이다 T라는 값은 임의로 적은 것 뿐 원하는 단어 혹은 문자를 사용해도 된다

const Login=<T>(props:T)=>{
  ...
}
onHandle("123") // ok
onHandle(0) // ok
onHandle(null) // ok

업그레이드를 해보자
아래처럼 되면 string타입만 props로 넘길 수 있다는 의미가 된다.

const onHandle=<T extends string>(args:T)=>{
}
onHandle("jwj") // ok
onHandle(123) // no
onHandle(null) //no

이렇게 하면 string과 number타입 모두 된다

const onHandle=<T extends string | number>(args:T)=>{
}
onHandle("jwj") // ok
onHandle(123) // ok
onHandle(null) //no

이렇게까지만 보면 그래서 뭘 어떻게 응용해서 사용하라는 건지 감이 잘 안잡힌다. string,number를 타입지정해서 쓰는것과 별반 다른게 없어보이기 때문이다.
이제 어떻게 실무에서 사용하기 좋은지에 대해서 알아보겠다.



공용컴포넌트들을 만들게 되면 1개의 props에 여러 유니온 타입이 들어 올수있다.
아래처럼 사용하면 props 타입을 필요에 따라 별도로 추가해서 사용하기에 사용성이 떨어진다.

type A = "kim" | "lee" | "park"
type B = "jang" | "choi" | "jo"

const Login=(props:{ data: A | B })=>{
...
}
<Login data={"kim"}/>

이때 제네릭을 쓰면 공통컴포넌트에서는 별도로 타입을 지정을 해주지 않았지만 공통컴포넌트를 사용하는 곳에서 타입을 지정을 해주었기에 해당 타입에 맞는 데이터들만 넘길 수 있게 되었다.

type A = "kim" | "lee" | "park"
type B = "jang" | "choi" | "jo"

type LoginProps<T> = {
 data:T
}

const Login=<T extends string>(props: LoginProps<T>)=>{
...
}

<Login<A> data={"kim"}/> // ok
<Login<B> data={"jang"}/> // ok
<Login<A> data={"jang"}/> // no

실제로 사용해본 꿀팁 중 하나는 key이름들을 Generic타입으로 넘기고 이를 이용해서 객체의 key이름으로 사용하는 것이다


type LoginProps<T> = {
 data:Record<T,string>
}

const Login=<T extends string>(props: LoginProps<T>)=>{
...
}

<Login< "kim" | "lee" | "park"> 
	data = {
    	kim: "test1",
        lee: "test2",
        park: "test3",
    }/>
<Login< "jang" | "choi" | "jo"> 
	data = {
    	jang: "test1",
        choi: "test2",
        jo: "test3",
    }/>

위와 같은 방법으로 공용컴포넌트를 만들때 props의 타입을 단일타입들(유니온타입을 or로 쓰는것도 포함)로 사용하는 것 보단 폭 넓게 사용이 가능하다는 장점이 있다.

profile
모르는게 너무 많아

0개의 댓글