TypeScript -7-

mh·2022년 5월 3일
0

TypeScript

목록 보기
7/17
post-thumbnail

Photo by Matheus Cenali on Unsplash

generic의 실제 사용사례

  • 대부분 이런식으로는 코드를 작성하지 않음
type SuperPrint = <T>(a: T[]) => T
  
const superPrint: SuperPrint = (a) => a[0]

const a = superPrint([1,2,3,4]);
const b = superPrint([true, false, true]);
const c = superPrint(["a", "b", "c"]);
const d = superPrint([1,2,"a",true,false,"b"]);
  • 직접 콜 시그니처를 만들일이 거의 없을거임
  • 다른 패키지나 라이브러리를 사용하고 라이브러리가 제네릭을 통해 생성됨
  • 하지만 라이브러리를 만들거나, 다른 개발자가 사용할 기능을 개발하는 경우엔 제네릭이 유용함
  • 그 외에는 직접 제네릭을 작성하진 않고 사용만할 경우가 많을거임
  • Next.js, nestJS, React 등에서 사용
  • 제네릭을 사용하고 타입스크립트에게 제네릭을 보냄
  • 제네릭을 사용하는 콜 시그니쳐 사용

generic의 다른 사용방법

  • 콜 시그니처를 작성하는 것 외의 다른 사용방법
```ts
type SuperPrint = <T>(a: T[]) => T
  
const superPrint: SuperPrint = (a) => a[0]
  • 이 부분에서 첫줄에서는 콜 시그니처를 직접 생성
  • 두번째줄은 타입으로 사용
  • 사실 이건 모두 일반 함수로 대체 할 수 있음
function superPrint<V>(a: V[]){
	return a[0]
}
  • Type로 만든거랑 똑같음

  • 전에꺼랑 비교 (이건 인자를 두개 받는것)
function superPrint<V>(a: V[]) {
    return a[0]
}

const a = superPrint<boolean>([1,2,3,4])
const b = superPrint([true,true,false])
const c = superPrint(["a","b","c"])
const d = superPrint([1,"ab",true,"123"])

  • 위 그림에서 function superPrint<number> 대신 <boolean>을 직접 넘겨준다면
    const a = superPrint<boolean>([1,2,3,4]) <- 에러
  • 타입스크립트에 boolean을 덮어씌웠기 때문에 타입스크립트는 V에 들어가는 값이 boolean이라 인식 -> 에러발생, 이렇게 타입을 명시하는 것이 가능하지만 좋지 않은 방법임
  • 항상 타입스크립트가 타입을 추론할 수 있게 만드는게 가장 좋음

generic으로 코드재사용하기

type Player= {
    name:string
    extraInfo:
}

extraInfo를 가진 Player type을 만들때

type Player=<E>{
    name:string
    extraInfo:E
}

any를 사용하면 보호장치가 없기 때문에 E라는 제네릭을 받게 할 수 있음 (꼭 E라고 할 필요 없음)

bob이라는 플레이어를 만들고 extraInfo엔 object가 들어가게 설정

const bob: Player<{}>

object 내부에는 favFood:string을 넣어줌

const bob: Player<{favFood:string}>

ExtraInfo 에 favfood를 작성하기

type Player=<E>{
    name:string
    extraInfo:E
}

const bob: Player<{favFood:string}> = {
    name:"bob",
    extraInfo: {
        favFood:"krabby patty"
    }
}

Player를 따로 빼서 줄여보기

type Player=<E>{
    name:string
    extraInfo:E
}

type bobPlayer = Player<{favFood:stirng}>

const bob: bobPlayer = {
    name:"bob",
    extraInfo: {
        favFood:"krabby patty"
    }
}

bobExtra 타입을 만들고 Plyaer타입의 제네릭 안에 넣어주기

넣어준 값을 bobPlyaer라는 새로운 타입으로 만듦

bob의 타입을 bobPlayer로 지정

type Player<E> = {
    name:string
    extraInfo:E
}

type bobExtra = {
    favFood:string
}

type bobPlayer = Player<bobExtra>

const bob: bobPlayer = {
    name:"bob",
    extraInfo: {
        favFood:"krabby patty"
    }
}

이런식으로 타입을 생성하고 그 타입에 또다른 타입을 넣어서 사용할 수 있음

type Player<E> = {
    name:string
    extraInfo:E
}

type bobExtra = {
    favFood:string
}

type bobPlayer = Player<bobExtra>

const bob: bobPlayer = {
    name:"bob",
    extraInfo: {
        favFood:"krabby patty"
    }
}

const dungEater: Player<null> = {
    name: "Dung Eater",
    extraInfo:null
}

이런식으로 재사용도 가능함

많은 타입중에 바뀔 수 있는 값이 있다면 거기에 제네릭을 넣으면 됨

type Player<E> = {
    name:string
    extraInfo:E
}

이처럼 제네릭은 함수 뿐만 아니라 다른곳에서도 쓰임

라이브러리의 generic

타입스크립트의 기본적인 타입은 제네릭으로 만들어져 있음

Array타입의 arrNumbers 타입

type arrNumbers

타입스크립트의 표준 라이브러리를 보면 Array가 Interface로 되있는걸 볼 수 있고
interface Array<t>var Array: Array... <T>를 제네릭으로 받는 것을 볼 수 있음

제네릭에 number를 넣어 number로 된 array로 지정

type arrNumbers = Array<number>

let a:arrNumbers = [1, 2, 3, 4]

이런 구조를 자주 보게 됨
제네릭을 사용하는 또다른 방법임

function printAllNumbers(arr: number[])

요렇게 제네릭을 사용할수도 있음

function printAllNumbers(arr: Array<number>)

다른 패키지,라이브러리에도 제네릭을 사용한 타입이 지정된 함수를 볼 수 있음.
거기에 무슨 타입을 사용할건지만 넘겨주면 됨

리액트에서 Generic 사용하기

useState는 제네릭을 받음

그렇기 떄문에 useState() 이렇게 사용하면 타입스크립트는 state 타입을 알 수 없음

대신 이렇게 사용해야함

useState<number>()

사용자가 제네릭를 보내면 useState의 콜 시그니처가 number 타입의 useState가 됨.

profile
🤪🤪🤪🤪🤪

0개의 댓글