본문 바로가기
Front-End/Typescript

Generics Recap

by developerDoorold 2022. 12. 16.

문가가 공부한 기록입니다. 부정확한 내용은 편히 지적 부탁드립니다.


 

//call signature
type SuperPrint = <T>(a: T[]) => T

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

const a = superPrint([1, 2, 3, 4]);
const b = superPrint([true, false, false]);
const c = superPrint(["1", "2", "3"]);
const d = superPrint([1, 2, true, false, "무야호"]);
console.log(a, b, c, d); // 1 true 1 1

제네릭(Generics)은 기본적으로 placeholder를 사용해 코드의 타입을 우리가 작성한 코드의 타입 기준으로 바꿔준다. 이 말은 즉, 타입스크립트는 우리의 코드를 보고 타입을 알아낸다는 것이다. 소오름!!

그런데 누군가는 말할 수 있다. 아 그러면 그냥 타입에 any 박으면 되는 거 아닌가요오오?? 에러도 안 나는데???

 

//call signature
type SuperPrint = (a: any[]) => any;

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

const a = superPrint([1, 2, 3, 4]);
const b = superPrint([true, false, false]);
const c = superPrint(["1", "2", "3"]);
const d = superPrint([1, 2, true, false, "무야호"]);
console.log(a, b, c, d); // 1 true 1 1

위와 같이 any를 갈겨버리게 되면 타입스크립트는 더 이상 우리를 지켜주지 못한다. a, b, c, d 모두가 any기 때문이다. 무슨 말이냐고?

 

any를 사용한 경우, 에러가 발생하지 않는다.(보호받지 못한다.)
제네릭을 사용한 경우, 에러가 발생한다.(보호받는다)

예를 들어 d.toUpperCase()를 사용하게 되면 에러가 난다. 왜냐면 superPrint는 배열의 첫 번째 요소를 리턴해주는데  d의 첫번째 요소는 number이다. 안타깝지만 숫자는 대문자가 없거든요. 아무튼 any 웬만하면 쓰지 말란 말이야~~

 

제네릭은 우리가 요구한 대로 signature를 생성해줄 수 있는 도구라고 생각하면 된다. 기억하자! 우리가 작성해야 할 Call signature를 생각하기 전에 타입스크립트가 우리를 위해서 우리의 코드를 공부할 것이다. 

 

이제 superPrint 타입에 제네릭을 하나 더 추가하고 싶다고 해보자. 어떻게 해야 할까? 아주 쉽다.

 

//call signature
type SuperPrint = <T, M>(a: T[], b:M) => T;
const superPrint: SuperPrint = (a) => a[0];

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

제일 먼저 해야할 일은 , 제네릭을 사용할 것이라고 말해주고 이름을 작성하면 된다. 이름은 무엇이든 관계없다.(M, T, V 등등) 그리고 우리가 어디에서 이 제네릭을 사용할 것인지 말해주면 된다.(위의 경우는 두 번째 인자 b를 M으로 설정했다.) 타입스크립트는 제네릭을 처음 인식했을 때와 제네릭의 순서를 기반으로 제네릭의 타입을 알게 된다. 그리고 우리의 요구에 따라서 각기 다른 Call signature를 생성한다.

 

두번째 인자b의 제네릭을 M으로 설정했을때 아래에서 에러가 발생하는 모습이다.
함수들의 두번째 인자값을 넣어주니 에러가 모습을 감췄다.

 

 

+참고자료
https://nomadcoders.co/typescript-for-beginners/lectures/3676

댓글