제네릭 소개

woodstock·2024년 1월 30일
0
post-thumbnail

제네릭이란

제네릭이란 함수나 인터페이스, 타입 별칭, 클래스 등을 다양한 타입과 함께 동작하도록 만들어주는 타입스크립트의 기능 중 하나이다.

제넥릭이 필요한 상황

다음과 같이 호출 결과를 저장하는 num, str 등의 변수가 any 타입으로 추론되면 문제가 발생한다.

function func(value: any) {
  return value;
}

let num = func(10);
let str = func("string");

num.toUpperCase()

num에는 분명 Number 타입의 값 10이 저장되어 있을 것이다. 그러나 any 타입으로 추론되어 버렸기 때문에 toUpperCase 등의 String 타입의 메서드를 사용해도 타입스크립트가 오류를 감지하지 못한다. 이 코드는 결국 실제로 실행하면 런타임 오류를 발생시키는 아주 위험한 상태가 되는 것이다.

이번에는 매개변수의 타입을 unknown타입으로 정의해보자.

function func(value: unknown) {
  return value;
}

let num = func(10);
// unknown 타입

let str = func("string");
// unknown 타입

num.toUpperCase(); // ❌
num.toFixed(); // ❌

toUpperCase 같은 메서드 호출은 방지할 수 있으나 toFixed같은 Number타입의 메서드 호출도 함께 오류로 판단하게 된다.

따라서, num에 10이 저장될 것이 분명한데도 이 값을 사용하려면 다음과 같이 비 효율적으로 타입 좁히기를 이용해야 한다.

function func(value: unknown) {
  return value;
}

let num = func(10);
// unknown 타입

let str = func("string");
// unknown 타입

if (typeof num === "number") {
  num.toFixed();
}

이런 상황에서 제네릭을 이용하면 문제는 간단히 해결된다.

제네릭(Generic) 함수

제네릭 함수는 두루두루 모든 타입의 값을 다 적용할 수 있는 그런 범용적인 함수라고 이해할 수 있다.

function func<T>(value: T): T {
  return value;
}


제네릭 함수를 호출할 때 다음과 같이 타입 변수에 할당할 타입을 직접 명시하는 것도 가능하다.

function func<T>(value: T): T {
  return value;
}

let arr = func<[number, number, number]>([1, 2, 3]);

위 코드의 흐름은 다음과 같다.
1. T[Number, Number, Number] 튜플 타입이 할당됨
1. 매개변수 value와 반환값 타입이 모두 튜플 타입이 됨

만약 위 코드에서 타입 변수에 할당할 타입을 튜플 타입으로 설정하지 않았다면 Tnumber[] 타입으로 추론 되었을 것이다. 타입스크립트는 타입을 추론할 때 항상 일반적이고 좀 더 범용적인 타입으로 추론하기 때문이다.

이렇듯 타입 변수에 할당하고 싶은 특정 타입이 존재한다면 함수 호출과 함께 꺽쇠를 열고 직접 명시해주는게 좋다. 그렇지 않은 대다수의 상황에서는 알아서 잘 추론되기 때문에 굳이 타입 변수를 설정하지 않아도 된다.

profile
해내는 사람

0개의 댓글