V-logue

[Typescript] 노마드코더 TypeScript로 블록체인 만들기 (3-4) 본문

발자취/Typescript

[Typescript] 노마드코더 TypeScript로 블록체인 만들기 (3-4)

보그 2022. 9. 7. 23:25

Conclusions

type SuperPrint = <x,y>(a:x[], b:y) => x

const superPrint : SuperPrint = (a) => a[0]

const a = superPrint([1 ,2 , 3, 4], "x");
const b = superPrint([true, false, true, false], 1);
const c = superPrint(["a", "b", "c", "d"], false);
const d = superPrint([1,"2",true,"hello"], []);

이전까지 generic에 대해서 배워봤다. 하지만, 일상적으로 generic을 사용해
call signature를 사용하게 될 것이라고는 생각하지 않는다.
보통 다른 잘 만들어진 패키지, 라이브러리를 사용하게 될 것이다.
혹시 내가 패키지나 라이브러리를 개발하게 될 경우라면 generic이 유용하게 사용될 것이다.
call signature를 사용할일은 적겠지만, generic 자체는 next.js nest.js react js를 사용한다면
generic을 일상적으로 사용하게 될 것이다.

generic의 일반적인 사용말고 다른 사용도 존재한다.

function SuperPrint<x>(a : x[]){
    return a[0]
}

위와 같은 방식으로 const superPrint : SuperPrint = (a) => a[0]를 구현할 수도 있다.
항상 TS가 이게 어떤 타입인지 추론할 수 있도록 코드를 짜는게 좋다.
만약 제네릭을 덮어쓰게 된다면

function superPrint<x,y>(a : x[], b:y){
    return a[0]
}

const a = superPrint<boolean, String>([1 ,2 , 3, 4], "x");

위와 같은 형식으로 사용하게 된다면, 'number' 형식은 'boolean' 형식에 할당할 수 없습니다.
라는 메세지를 받게 된다. 제네릭을 덮어쓴 overwrite(덮어쓰기) 했기 때문이다.
a : boolean이 되버렸기 때문에 number형식으로는 사용할 수 없는 것이다.
여기까지 제네릭의 또 다른 사용법 1이였고 또 다른 사용법 2도 있다.

type Player<X> = {
    name: String
    extraInfo :X 
}


Player라는 타입에 extraInfo가 있다고 치면, extraInfo는 Object가 될 수도 있고, boolean값이 될 수도 있다.
any를 사용하면 보호를 받지 못하기 때문에 제네릭을 사용할 수 있다.
nico라는 플레이러를 생성하고, 만약 extraInfo에 object가 들어간다면 

const nico : Player<{favFood : string}> = {
    name : "nico",
    extraInfo : {
        favFood : "Kimchi"
    }
}


이런식으로 사용할 수도 있지만, 이걸 좀더 세밀하게 나눠보면 

type Player<X> = {
    name: String
    extraInfo :X 
}

type NicoExtra = {
    favFood : string
}

type NicoPlayer = Player<NicoExtra>;

const nico : NicoPlayer = {
    name : "nico",
    extraInfo: {
        favFood : "Kimchi"
    }
}


이제 여기에 Lynn Player를 만든다고 치고, Lynn이 extraInfo가 없다고 가정하면

const Lynn : Player<null> = {
    name: "Lynn",
    extraInfo : null
}

모든 Player는 name을 가지고 있으니, Lynn도 네임은 있을 것이고 extraInfo가 없다면
Null값을 넣어 의도적으로 값이 없음을 명시하면 된다.

만약 많은 것들이 있는 큰 타입이 있는데, 그 중 몇가지의 값이 달라질 수 있는 타입이라면
제네릭을 넣어 재사용성을 올릴 수 있다.
대부분의 기본적인 TS 타입은 generic으로 만들어져 있다. 예를들어 Array를 생성한다고 치면,

type NumArray = Array


Array의 형식을 지정하지 않는 경우, 다음과 같은 에러메세지가 나타나게 된다.
'Array<T>' 제네릭 형식에 1 형식 인수가 필요합니다.
자동완성의 TS 표준 라이브러리를 보면 interface Array<T>var Array: ArrayConstructure
라는 메세지와 함께, 표준 라이브러리인 Array가 제네릭을 사용하고 있는 것을 알 수 있다.

type NumArray = Array<number>

let a : NumArray = [1, 2, 3, 4];

잘 작동하는 모습이다. 위와 같은 형태가 generic의 또 다른 사용 형태이다.

function printAllNumbers(arr: Array<number>){

}

generic은 위와 같은 방식으로도 사용할 수 있고, Array<number>는 number[]와 같은 말이다.

Comments