공부공부/TS

[typescript 핸드북] 07. 제네릭

고생쨩 2024. 2. 19. 09:33
728x90

typescript 핸드북 학습내용 정리
https://typescript-kr.github.io/pages/the-handbook.html

제네릭

사용자는 제네릭을 통해 여러 타입의 컴포넌트나 자신만의 타입을 사용할 수 있음

제네릭의 Hello World

any를 써서 구현한 경우

function identity(arg: any): any {
    return arg;
}

제네릭으로 구현한 경우

function identity<T>(arg: T): T {
    return arg;
}

타입변수 T는 유저가 준 인수의 타입을 캡처하고, 이 정보를 나중에 사용할 수 있게 함.

// 두가지 호출 방법

// 명시적 선언
let output = identity<string>("myString"); // 출력 타입은 'string'입니다.

// 인수 추론
let output = identity("myString"); //출력 타입은 'string'입니다.

제네릭 타입 변수 작업

function loggingIdentity<T>(arg: T): T {
  console.log(arg.length); // 오류: T에는 .length 가 없습니다.
  return arg;
}
function loggingIdentity<T>(arg: T[]): T[] {
  console.log(arg.length); // 배열은 .length를 가지고 있습니다. 따라서 오류는 없습니다.
  return arg;
}

위와 아래 동일

function loggingIdentity<T>(arg: Array<T>): Array<T> {
  console.log(arg.length); // 배열은 .length를 가지고 있습니다. 따라서 오류는 없습니다.
  return arg;
}

제네릭 타입

기본 구조

function identity<T>(arg: T): T {
  return arg;
}

let myIdentity: <T>(arg: T) => T = identity;
//매개변수 이름은 달라도 됨 T가 아닌 U 등

객체 리터럴 타입의 함수 호출 시그니처로 작성할 수 있음

function identity<T>(arg: T): T {
  return arg;
}

let myIdentity: { <T>(arg: T): T } = identity;

위 내용들로 제네릭 인터페이스를 작성할 수 있음

interface GenericIdentityFn {
  <T>(arg: T): T;
}

function identity<T>(arg: T): T {
  return arg;
}

let myIdentity: GenericIdentityFn = identity;

제네릭 매개변수를 전체 인터페이스의 매개변수로 옮기고 싶을때

interface GenericIdentityFn<T> {
  (arg: T): T;
}

function identity<T>(arg: T): T {
  return arg;
}

let myIdentity: GenericIdentityFn<number> = identity;
// 특정 타입인수가 필요함 (T 불가능)

제네릭 제약조건

// 제약조건을 interface로 설정
interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);  // 이제 .length 프로퍼티가 있는 것을 알기 때문에 더 이상 오류가 발생하지 않습니다.
    return arg;
}
loggingIdentity(3);  // 오류, number는 .length 프로퍼티가 없습니다.
loggingIdentity({length: 10, value: 3}); // 필요한 값을 전달해야함

제네릭 제약조건에서 타입 매개변수 사용

// 제네릭 타입 T와 K(keyof T)를 이용하여 getProperty 함수의 인자 key가 T 객체의 프로퍼티 중 하나임을 보장함.
function getProperty<T, K extends keyof T>(obj: T, key: K) {
    return obj[key];
}

let x = { a: 1, b: 2, c: 3, d: 4 };

getProperty(x, "a"); // 성공
getProperty(x, "m"); // 오류: 인수의 타입 'm' 은 'a' | 'b' | 'c' | 'd'에 해당되지 않음.

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.