Notice
Recent Posts
Recent Comments
Link
관리 메뉴

윤일무이

[TypeScript] 제네릭 활용 본문

❔ TypeScript/💭 한 입 크기 TypeScript

[TypeScript] 제네릭 활용

썸머몽 2023. 12. 21. 18:31
728x90

제네릭을 활용하자

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

const [a, b] = swap("1", 2);
  • 2개의 타입 변수가 필요한 위와 같은 상황에서는 타입 변수를 T, U 이렇게 2개를 사용할 수 있다.
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는 배열의 요소 타입으로 할당된다.
  • 변수 num에서 함수를 호출할 때 Number[] 타입의 값을 전달했으므로 T의 타입은 Number로 추론된다.
  • 변수 str에서 함수를 호출할 때 (String | Number)[] 타입의 값을 전달했으므로 T의 타입은 String | Number로 추론된다.
function returnFirstValue<T>(data: [T, ...unknown[]]) {
  return data[0];
}

let str = returnFirstValue([1, "hello", "mynameis"]);
// number
  • 반환값의 타입을 배열의 첫 번째 요소의 타입이 되게 하려면 튜플 타입과 rest 파라미터를 사용한다.
  • 우리가 구할 것은 '배열'의 '첫 번째' 요소 타입이기 때문에, 함수 매개변수의 타입을 정의할 때 튜플 타입을 이용해 첫 번째 요소의 타입은 T, 나머지 요소의 타입은 unknown[]으로 지정해 길이도, 타입도 상관 없도록 정의한다.
  • 따라서 변수 str에서 함수를 호출할 때 T는 첫 번째 요소 타입인 Number 타입이 되어 함수 반환값 타입도 Number 타입이 된다.
function getLength<T extends { length: number }>(data: T) {
  return data.length;
}

getLength("123");            // ✅

getLength([1, 2, 3]);        // ✅

getLength({ length: 1 });    // ✅

getLength(undefined);        // ❌

getLength(null);             // ❌
  • 타입 변수를 제한한다는 것은 함수를 호출하고, 인수로 전달할 수 있는 값의 범위에 제한을 두는 것
  • 타입 변수를 적어도 length 프로퍼티를 갖는 객체 타입으로 제한하려고 한다.
  • 타입 변수를 제한할 때는 확장을 이용한다.
  • T extends { length: number }로 하면, T는 { length: number } 객체 타입의 서브 타입이 된다.
  • 따라서 T는 무조건 Number 타입의 프로퍼티 length를 가지고 있는 타입이 되어야 한다.
  • 4, 5번의 경우 length 프로퍼티가 존재하지 않으므로 오류가 발생한다.

 


 

 **출처: 한 입 크기로 잘라먹는 타입스크립트 (인프런, 이정환 강사님)

728x90