제네릭

윤영훈·2021년 8월 21일
0

제네릭의 사전적 정의

제네릭은 재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 특징입니다.

특히, 한가지 타입보다 여러 가지 타입에서 동작하는 컴포넌트를 생성하는데 사용됩니다.

제네릭의 한 줄 정의

제네릭이란 타입을 마치 함수의 파라미터처럼 사용하는 것을 의미합니다.

제네릭을 사용하는 이유

  • 여러가지 타입을 허용하고 싶을 때,

*** any를 쓴다면 함수의 인자로 어떤 타입이 들어갔고 어떤 값이 반환되는지 알 수가 없다. 타입을 검사하지 않기 때문에 !

기본 사용법

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

* any를 쓰는 것은 함수의 arg가 어떤 타입이든 받을 수 있다는 점에서 제네릭이지만, 실제로 함수가 반환할 때 어떤 타입인지에 대한 정보는 잃게 됩니다.** 만약 number 타입을 넘긴다고 해도 any 타입이 반환된다는 정보만 얻을 뿐입니다.

우리는 무엇이 반환되는지 캡처할 방법이 필요합니다. 여기서는 값이 아닌 타입에 적용되는 타입 변수를 사용할 것입니다.

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

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

호출 방법

# 1
let output = identity<string>("myString"); // 출력 타입은 string입니다.

# 2 
output = identity("myString") // 출력 타입은 'string'입니다.

#1 : T를 string으로 명시해주고 사용

#2 : 가장 일반적인 방법으로 타입 인수 추론을 사용합니다. 우리가 전달하는 인수에 따라서 컴파일러가 T의 값을 자동으로 정하게 하는 것입니다. 인수 추론은 코드를 간결하고 가독성 있게 하는 데 있어 유용하지만, 더 복잡한 예제에서 컴파일러가 타입을 유추할 수 없는 경우에 명시적으로 인수 전달이 필요할 수도 있습니다.

제네릭 타입 변수 작업

function logText<T>(text: T): T {
  return text;
}

만약 여기서 함수의 인자로 받은 값의 length를 확인하고 싶다면 ? 아마 아래와 같이 작성할 것입니다.

function logText<T>(text: T): T {
  console.log(text.length);
  return text;
}

이 코드는 컴파일러에서 에러를 발생시킵니다. 왜냐하면 text에 .length가 있다는 단서는 어디에도 없기 때문입니다.

위 제네릭 코드의 의미를 살펴보면 함수의 인자와 반환 값에 대한 타입을 지정하진 않았지만, 입력 값으로 어떤 타입이 들어왔고 반환 값으로 어떤 타입이 나가는지 알 수 있습니다. 따라서, 함수의 인자와 반환 값 타입에 마치 any를 지정한 것과 같은 동작을 한다는 것을 알 수 있습니다. 그래서 설령 인자에 number 타입을 넘기더라도 에러가 나진 않습니다. 이러한 특성 때문에 현재 인자 text에 문자열이나 배열이 들어와도 아직은 컴파일러 입장에서 .length를 허용할 순 없습니다. 왜냐하면 number가 들어왔을 때 .length를 코드가 유효하지 않기 때문입니다.

그래서 이런 경우에 아래와 같이 제네릭에 타입을 줄 수 있습니다.

function logText<T>(text: T[]): T[] {
    console.log(text.length);
    return text;
}

logText의 타입을 " 제네릭 함수 logText는 타입 매개변수 T와 T 배열인 인수 text를 취하고 T배열을 반환한다" 라고 읽을 수 있습니다. 만약 우리가 number 배열을 넘기면 T가 number에 바인딩 되므로 함수는 number 배열을 얻게 됩니다. 전체 타입변수를 쓰는 것보다 하나의 타입으로써 제네릭 타입변수 T를 사용하는 것은 굉장한 유연함을 제공합니다.

위 예제를 다음과 같이 좀 더 명시적으로 제네릭 타입을 선언할 수 있습니다.

function logText<T>(text: Array<T>): Array<T> {
    console.log(text.length);
    return text;
}
  • 추가할 항목 : 제네릭 타입, 제네릭 클래스

0개의 댓글