Front-end/Typescript

Typescript Generic

아지송아지 2022. 3. 22. 16:21

안녕하세요!

오늘은 typescript의 제네릭(Generic)에 대해 알아보겠습니다.

개발을 하다 보면 재사용하는 함수는 따로 제작하여 사용하고는 합니다.

 

예를 들어 매개변수를 그대로 리턴하는 함수가 있다고 생각해 봅시다.

function returnParam(item: number): number{
	return item;
}

현재는 number타입만 있지만 string타입도 추가해야합니다.

function returnParam(item: number|string): number|string{
	return item;
}
const test = returnParam("test");

 

유니온타입을 이용하여 추가했습니다.

위 코드에서 test는 number | string 타입이기 때문에 공통되는 타입의 함수밖에 쓰지 못합니다.

또한 타입이 늘어날 때마다 타입을 계속 추가해 주어야 하는 불필요함이 있습니다.

이런 문제점을 해결하기 위해서는 제네릭 타입을 사용해야 합니다.

 

 

Generics


사용법

function returnParam<Type>(item: Type): Type{
	return item;
}

제네릭 타입의 기본적인 구조입니다.

전달받은 Type이 매개변수와 리턴 값에 사용되는 것을 볼 수 있습니다.

Type 외에 다른 이름을 사용하셔도 괜찮습니다.

 

// 명시적으로 타입을 전달하는 경우
let test = returnParam<string>("test");

// 타입을 추론하는 경우
let hello = returnParam("hello");

사용방법입니다.

명시적으로 타입을 전달하는 방법과 타입을 알아서 추론하는 방법 두 가지가 있습니다.

일반적으로 후자의 방법이 자주 사용됩니다. 하지만 타입이 복잡해져 타입 추론이 어려울 경우 명시적으로 타입을 전달하는게 좋습니다.

 

 

타입제한

function genericArray<Type>(item: Type): Type{
    console.log(item.length); // 오류 - Type에는 length가 없습니다.
    return item;
}
genericArray(["hello"])

다음과 같이 길이를 구하고 싶은 경우가 있습니다.

하지만 앞서 정의하였듯 제네릭타 입에는 무슨 타입이 올지 모르고, Type이라는 속성에는 length가 없습니다.

따라서 저희는 Type을 배열로 제한해보겠습니다.

 

function genericArray<Type>(item: Type[]): Type[]{
	console.log(item.length); // 성공
	return item;
}
genericArray(["hello"])

Type을 단독으로도 사용 가능하지만 []와 함께 사용하는것도 가능합니다.

 

 

 

다른 방식의 사용

지금까지 제네릭 함수를 제작했습니다.

그 외 다르게 사용하는 제네릭 타입에 대해 알아보겠습니다.

 

1. 함수타입을 선언할때도 사용합니다.

function returnParam<Type>(item: Type): Type{
	return item;
}

let genericType1: <Type>(arg: Type)=>Type = returnParam;

let genericType2: { <Type>(arg: Type):Type } = returnParam;

 

2. interface에서 활용합니다.

// 함수
interface IGenericType<Type>{
	(arg:Type): Type;
}
function returnParam<Type>(item: Type): Type{
	return item;
}
let genericType1: IGenericType<number> = returnParam;


// 변수
interface IGenerics<T> {
    value:T,
    id:number,
}
const genericObjStr: IGenerics<string> = {value:"hello", id:0};
const genericObjNum: IGenerics<number> = {value:10, id:0};

 

 

 

참고 : 

https://www.typescriptlang.org/ko/docs/handbook/2/generics.html#%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%81%B4%EB%9E%98%EC%8A%A4-generic-classes