[TS] 제네릭 타입 변수 응용

TIL

제네릭 함수 활용 사례

사례 1: 여러 개의 타입 변수

두 값의 위치를 바꾸는 swap 함수를 만들어 보자.

function swap(a: any, b: any) {
  return [b, a];
}

const [a, b] = swap(1, 2);

any타입을 사용하면 타입 안정성이 보장되지 않는다.

 

2개의 타입 변수가 필요한 상황이라면 다음과 같이 T, U 처럼 여러 개의 타입 변수를 사용할 수 있다.

function swap<T, U>(a: T, b: U) {
  return [b, a];
}

const [a, b] = swap("1", 2);

위 코드에서 T는 string 타입으로, U는 number 타입으로 추론된다.

반환값은 [U, T] 즉, [number, string] 튜플 타입이 된다.

 

사례 2: 배열 요소 타입 추론

배열의 첫 번째 요소를 반환하는 함수를 만들어보자.

function returnFirstValue(data: any) {
  return data[0];
}

let num = returnFirstValue([0, 1, 2]);
let str = returnFirstValue([1, "hello", "mynameis"]);

 

다양한 배열 타입을 인수로 받는 제네릭 함수는 다음과 같이 만들 수 있다.

function returnFirstValue<T>(data: T[]) {
  return data[0];
}

let num = returnFirstValue([0, 1, 2]); // number
let str = returnFirstValue([1, "hello", "mynameis"]); // number | string

함수 매개변수 data의 타입을 T[]로 설정했기 때문에 배열이 아닌 값은 인수로 전달할 수 없으며, 배열을 인수로 전달하면 T는 배열의 요소 타입으로 추론된다.

첫 번째 호출에서는 number[] 타입의 값을 전달했으므로 T는 number 타입으로 추론되며, 반환값 타입도 number가 된다.

두 번째 호출에서는 (number | string)[] 타입의 값을 전달했으므로 T는 number | string 타입으로 추론되며, 반환값 타입도 number | string가 된다.

 

사례 3: 첫 번째 요소 타입만 추론

위 사례에서 반환값의 타입을 배열의 첫 번째 요소 타입으로 정확히 지정하려면 튜플 타입과 나머지 파라미터를 이용하면 된다.

function returnFirstValue<T>(data: [T, ...unknown[]]) {
  return data[0];
}

let str = returnFirstValue([1, "hello", "mynameis"]); // number

함수 매개변수의 타입을 튜플 타입 [T, ...unknown[]]로 정의하면 첫 번째 요소의 타입은 T, 나머지 요소는 길이와 타입에 상관없이 받을 수 있다.

함수를 호출하고 [1, "hello", "mynameis"] 같은 배열을 인수로 전달하면 T는 첫 번째 요소의 타입인 number가 되며, 반환값 타입도 number가 된다.

 

사례 4: 타입 변수 제한하기

타입 변수를 제한한다는 것은 함수 호출 시 인수로 전달할 수 있는 값의 범위에 제한을 두는 것을 의미한다.

function getLength(data: any) {
  return data.length;
}

let var1 = getLength([1, 2, 3]);
let var2 = getLength("12345");
let var3 = getLength({ length: 10 });
let var4 = getLength(10); // 런타임 오류

any 타입을 사용하면 length 프로퍼티가 없는 값도 전달할 수 있어 위험하다.

 

타입 변수를 length 프로퍼티를 갖는 타입으로 제한해보자.

function getLength<T extends { length: number }>(data: T) {
  return data.length;
}

getLength("123");            // ✅
getLength([1, 2, 3]);        // ✅
getLength({ length: 1 });    // ✅
getLength(10);               // ❌

타입 변수를 제한할 때는 extends 키워드를 사용한다. T extends { length: number }로 정의하면 T는 { length: number } 객체 타입의 서브 타입이 된다.

즉, T는 무조건 number 타입의 length 프로퍼티를 가지고 있어야 한다. 따라서 문자열, 배열, length 프로퍼티를 가진 객체는 전달할 수 있지만, 숫자처럼 length가 없는 값은 전달할 수 없다.

'TIL' 카테고리의 다른 글

[TS] 제네릭 인터페이스와 타입 별칭  (0) 2025.11.04
[TS] map, forEach 메서드 타입 정의하기  (0) 2025.11.04
[TS] 제네릭  (0) 2025.11.04
[CS50] 컴퓨팅 사고 - 2진법  (0) 2025.11.03
[TS] 클래스와 접근제어자 사용 연습  (0) 2025.11.03
'TIL' 카테고리의 다른 글
  • [TS] 제네릭 인터페이스와 타입 별칭
  • [TS] map, forEach 메서드 타입 정의하기
  • [TS] 제네릭
  • [CS50] 컴퓨팅 사고 - 2진법
고견
고견
개발 자국 남기기
  • 고견
    개발자국
    고견
  • 전체
    오늘
    어제
    • 분류 전체보기 (157) N
      • Frontend (29)
        • Next.js (16)
        • JavaScript (7)
      • CS (19) N
        • 자료구조 (9)
        • 알고리즘 (5)
        • 운영체제 (4) N
        • 네트워크 (1) N
      • TIL (93)
      • Dev Log (16)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    typescript
    알고리즘
    CS
    App Router
    generic
    emotion diary
    react
    Spa
    javascript
    ai 감성 일기장
    useState
    바닐라 자바스크립트
    배열
    Pages Router
    함수 타입
    제네릭
    타입 좁히기
    자료구조
    memory
    Trouble Shooting
    페이지 라우터
    문자열
    cs50
    algorithm
    Next.js
    트러블 슈팅
    클래스
    인터페이스
    C
    앱 라우터
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
고견
[TS] 제네릭 타입 변수 응용
상단으로

티스토리툴바