[TIL] 241011_Typescript: 제네릭(1)

지코·2024년 10월 11일
0

Today I Learned

목록 보기
32/66
post-thumbnail

⚡️ 제네릭

  • T: 타입 변수, 인수의 타입에 따라 타입 변수의 타입이 달라짐.
  • 이 때 타입 변수의 타입은 함수 호출 시 결정됨.

제네릭 함수는 타입 변수<> 를 사용해서 표현한다.

예시에서 함수 func()는 사용자로부터 받은 인수를 그대로 반환하는 함수이다.
하지만 타입 변수를 사용하지 않고 매개변수인 value의 타입에 unknown, any 등을 사용하게 되면, 함수 func의 반환값을 저장하는 변수 num, bool의 타입은 unknown, any가 되어버린다. 우리가 원하는 건 인수의 타입이 변수의 타입이 되는 것!

따라서 제네릭 함수를 통해 위와 같이 선언하면, 인수의 타입에 따라 변수의 타입도 결정된다.

타입 변수를 내가 결정하고 싶다면

// Ex> 배열을 튜플로 정의하고 싶을 때
let arr = func<[number, number, number]>([1, 2, 3]);

위와 같이 함수를 호출할 때 제네릭으로 원하는 형태의 타입을 넣어주면 된다. 이 때 arr은 배열이 아닌 튜플로 결정된다.

⚡️ 타입 변수 응용하기

사례 1️⃣: 두 개 이상의 타입 변수를 사용해야 할 때.

필요한 만큼 여러 개의 타입 변수를 제네릭으로 선언해서 사용하면 된다.

function swap<T, U>(a: T, b: U) {
  return [b, a];
}
const [a, b] = swap("1", 2);

이 때 T는 string, U는 number 타입이 들어간다.

사례 2️⃣: 타입 변수에 배열, 튜플 타입을 적용할 때.

Ex1> 다음과 같이 매개변수의 타입에는 타입 변수+배열/튜플 을 사용한다.

function returnFirstValue<T>(data: T[]) {
  return data[0];
}
let num = returnFirstValue([0, 1, 2]);  // 0
let str = returnFirstValue(["hello", "myNameIs", "JiSoo"]); // hello

Ex2> 첫 번째 요소를 제외한 다른 요소들의 타입은 궁금하지 않을 때.
➡️ rest 키워드를 사용해서 다음과 같이 처리한다.

function returnFirstValue2<T>(data: [T, ...unknown[]]) {
  return data[0];
}
// str2의 타입이 number로 잘 추론됨
let str2 = returnFirstValue2([1, "hello", "myNameIs", "JiSoo"]); 

사례 3️⃣: 타입 변수의 조건을 설정할 때.

➡️ extends 키워드를 사용해서 다음과 같이 조건을 설정한다.

function getLength<T extends { length: number }>(data: T) {
  // length가 number인 property를 갖고 있는 T라는 타입 변수를 사용.
  return data.length;
}

let var1 = getLength([1, 2, 3]);  // 3
let var2 = getLength(["12345"]);  // 5
let var3 = getLength({ length: 10 }); // 10
// let var4 = getLength(10);  // length property가 없기 때문에 사용 불가능.

⚡️ map, forEach 메서드 타입 정의하기

1️⃣ map

const arr = [1, 2, 3];
const newArr = arr.map((it) => it * 2); // [2, 4, 6]

자바스크립트에서 map 메서드는 위와 같이 배열의 요소들 각각에 콜백 함수를 수행한 결과를 새로운 배열로 반환한다.
map 메서드를 정의해보면 위와 같이 정의할 수 있다.

// Ex1> number
map(arr, (it) => it * 2); 
// Ex2> string
map(["hi", "hello"], (it) => it.toUpperCase()); 
// Ex3> string, number
// 콜백함수의 반환값까지 string일 필요는 없으므로 타입 변수를 두 개 사용!
map(["hi", "hello"], (it) => parseInt(it)); 

타입 변수를 제네릭으로 선언한 후, 각 매개변수에서 그 타입 변수를 어떤 식으로 사용하는지 고민해보면 적용하기 어렵지 않다.
이 때 Ex3을 보면 타입 변수를 하나만 사용하기 어렵기 때문에 두 개의 타입 변수를 사용하도록 변경하였다.

2️⃣ forEach

const arr2 = [1, 2, 3];
arr2.forEach((it) => console.log(it));

forEach 메서드는 map 메서드와 다르게 반환값이 없고, 메서드를 사용하는 객체에 콜백 함수를 수행한 결과를 나타낸다.
forEach 메서드를 정의해보면 위와 같이 정의할 수 있다. 이 때 타입 변수를 적용하는 방식도 map 메서드를 정의할 때와 같다.

Reference

👩🏻‍🏫 한입 크기로 잘라 먹는 타입스크립트(TypeScript)

https://www.inflearn.com/course/한입-크기-타입스크립트

profile
꾸준하고 성실하게, FE 개발자 역량을 키워보자 !

0개의 댓글