본문 바로가기
C.W.K.
Stream
Lesson 02 of 07 · published

제네릭 함수: 한 구현으로 타입 관계를 반복해

~10 min · generics, functions, multiple-parameters

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"제네릭 함수는 어떤 타입이 들어와도 된다는 말보다, 들어온 타입이 다른 자리에도 같은 모습으로 나타난다는 말을 해."

하나의 타입 매개변수

head<T>(items: T[]): T | undefined는 배열 원소 타입을 T로 붙잡고 반환값에 그대로 사용해. 빈 배열 가능성 때문에 undefined도 함께 말해. 숫자 배열 호출에서는 number 또는 undefined, User 배열에서는 User 또는 undefined가 된다.

이런 함수는 타입마다 구현을 복사하지 않아도 되고 any로 정보를 버리지도 않아. 함수 몸은 한 번 쓰되 호출마다 구체 계약이 만들어지는 셈이야.

여러 타입 매개변수로 변환 관계를 나타내

map<T, U>(items: T[], fn: (item: T) => U): U[]는 입력 원소 T가 콜백을 거쳐 U로 바뀌고 결과 배열도 U가 된다는 관계를 적어. T와 U는 서로 다를 수 있고, 컴파일러는 배열과 콜백을 함께 보며 둘을 추론해.

타입 매개변수가 많아지면 T, U 같은 짧은 이름보다 Input, Result, Key처럼 역할을 드러내는 이름이 나을 수 있어. 짧은 범위에서는 관례가 읽기 좋고, 긴 공개 타입에서는 뜻이 읽기 좋아야 해.

추론 방향을 설계해

제네릭 함수의 사용감은 어느 인자에서 타입을 추론할 수 있는지에 달려. 호출자가 먼저 제공하는 값에서 T를 알아내고 뒤의 콜백 매개변수로 문맥을 흘려보내면 자연스러워. 반대로 반환값에서만 T를 정해야 하면 호출자가 타입 인자를 직접 적어야 할 수 있다.

head<T>는 배열 원소와 반환 타입을 연결하고, map<T, U>는 입력 T를 콜백의 출력 U와 연결해 U 배열을 만들어. 대부분의 호출에서는 인자에서 타입이 추론되지만, 추론할 정보가 없거나 의도와 다를 때는 identity<string>('x')처럼 명시할 수 있어.

타입 매개변수는 값 사이의 관계마다 하나씩 둬. 같아야 하는 것은 같은 T로, 독립적인 것은 다른 매개변수로 표현해.

Code

Generic 함수 — 하나 또는 여러 타입 parameter·typescript
// 한 타입 parameter — 입력과 출력의 관계.
function head<T>(arr: T[]): T | undefined {
  return arr[0];
}
const a = head([1, 2, 3]);          // a: number | undefined
const b = head(['hi']);              // b: string | undefined

// 두 타입 parameter — 입력과 callback 출력.
function map<T, U>(arr: T[], fn: (x: T) => U): U[] {
  return arr.map(fn);
}
const c = map([1, 2, 3], (n) => n.toString());  // c: string[]

// Argument 와 callback 함께에서 추론.
function findFirst<T>(arr: T[], predicate: (x: T) => boolean): T | undefined {
  for (const x of arr) if (predicate(x)) return x;
  return undefined;
}
const d = findFirst([{ id: 1 }, { id: 2 }], (u) => u.id === 1);  // d: { id: number } | undefined

External links

Exercise

두 배열의 같은 위치 원소를 쌍으로 묶는 zip<T, U>를 작성해. 숫자 배열과 문자열 배열을 넣었을 때 결과가 [number, string][]인지 확인해.
Hint
return a.map((x, i) => [x, b[i]])처럼 작성해. 반환 타입 [T, U][]가 각 쌍의 첫 번째와 두 번째 자리에 어떤 타입이 오는지 끝까지 보존하므로 호출자도 둘을 정확히 구분할 수 있어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.