본문으로 바로가기

Generics

category JavaScript/TypeScript 2021. 3. 12. 12:08

제네릭은 자바나 C에서 재사용이 가능한 함수에 다양한 타입의 파라미터를 받을 수 있게끔 하는 특징이다

제네릭 함수

제네릭 함수의 Hello World라는 identity함수를 만들어보자

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

identity 함수는 받은 파라미터를 그대로 반환하는 아주 간단한 함수이다

하지만 타입스크립트 처럼 들어오는 파라미터의 타입과 반환 타입이 미리 명시되어있다면 어떻게 해야 유동적으로 타입을 받을 수 있을까?

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

any를 사용하면 간단할 것 같다 어떤 타입이 들어오든 들어온 타입으로 반환할 수 있다

하지만 문제가 있는데

제네릭을 사용하는 identity 함수는 파라미터의 타입이 정의되면 리턴 타입도 정의되야한다

즉 파라미터에 number가 들어가면 리턴 타입은 number이어야 하지만 지금 함수에선 리턴 타입은 여전히 any이다

그렇기 때문에 필요한것이 타입 변수다

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

<>꺽새 안에 있는 것이 타입 변수인데 전달받은 타입 형태를 기억하고 차후에 다시 사용할 수 있게 해준다

string을 넘겨주면 파라미터와 반환 타입 둘 다 정의되는 것

사용법

만든 identity 함수를 사용해보자

방법은 두 가지가 있다

identity<string>('str');

identity('str');

첫 번째로 사용한 방법은 타입 변수로 사용될 T에 타입을 명시해주는 것

두 번째로 사용한 방법은 그냥 파라미터를 전달하는 것이다

타입을 명시하지않고 파라미터를 그냥 넘겨주게되면 타입스크립트가 타입추론을 통해서 T를 정의한다

여기서는 string이 된다

제네릭 타입 변수 작업

identity 함수에서 같이 제네릭 타입을 사용하기 시작하면

함수 내부에 코드를 작성할 때 타입스크립트가 제네릭 타입으로 변한 매개변수를 쓰게 만든다

identity 함수에서 arg의 길이를 알고싶다면 어떻게 해야할까?

function lengthIdentity <T>(arg : T) : T{
    arg.length();//에러
    return arg;
}

타입 T가 length를 가지고 있다는 정보가 어디에도 없기 때문에 이런 코드는 컴파일러에서 잡아낸다

제네릭 제약 조건

그럼 어떻게 해야할까

타입 변수에 .length를 가진 타입만 올 수 있게 제약 조건을 달면된다

제약 조건은 interface를 사용해서 만들어 줄 수 있다

interface Lengthwise {
    length: number;
}

이제 만든 조건을 타입 변수에 상속시켜서 타입스크립트가 이 변수에 들어올 수 있는 조건을 알 수 있게 만들어 주면 된다

interface Lengthwise {
    length: number;
}
function lengthIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);  // 이제 들어올 T에는 length 프로퍼티가 있다는 것을 앎
    return arg;
}

이런 조건을 걸었기 때문에 T에 length가 없는 타입이 들어올 경우 에러가 난다

lengthIdentity(123) // 에러

'JavaScript > TypeScript' 카테고리의 다른 글

Mapped Type  (0) 2021.10.25
유틸리티 타입  (0) 2021.10.24
Function  (0) 2021.03.11
클래스  (0) 2021.03.03
인터페이스  (0) 2021.03.02