모든 타입스크립트에 관련된 모든 포스트들은 제가 배운 주관적인 지식에 의거하므로 틀린게 있다면 댓글로 피드백 부탁드리겠습니다.
우선 타입스크립트 공식문서에 나와있는 Generic의 등장이유입니다.
잘 정의되고 일관된 API뿐만 아닌 재사용 가능한 컴포넌트를 구축하는 것도 소프트웨어 엔지니어링에서의 주요한 부분입니다. 현재의 데이터와 미래의 데이터 모두를 다룰 수 있는 컴포넌트는 거대한 소프트웨어 시스템을 구성하는 데 있어 가장 유연한 능력을 제공할 것입니다.
C#과 Java 같은 언어에서, 재사용 가능한 컴포넌트를 생성하는 도구상자의 주요 도구 중 하나는 제네릭입니다, 즉, 단일 타입이 아닌 다양한 타입에서 작동하는 컴포넌트를 작성할 수 있습니다. 사용자는 제네릭을 통해 여러 타입의 컴포넌트나 자신만의 타입을 사용할 수 있습니다.
여기에 설명을 덧데어 Generic으로 타입을 받는 함수에는 어떤 타입이던 들어갈수 있고 들어간 타입을 보장받을 수 있는 장점이 있습니다.
function checkNotNullGeneric<T>(arg: T | null): T{}
위의 코드처럼 함수명뒤에, 인자:T, 리턴값: T로 해줍니다.
왜 꼭 T로 해야되죠 ? GENERIC이나 내가 원하는 A나 B는 안되나요?
전혀 상관없습니다. 하지만 제가 위에서 T라고 한이유는 타입스크립트 공식 문서에서 그렇게 되있었고 통상적으로 Type의 약어로 T를 사용합니다.
하지만 타입스크립트의 기본타입중에 어떤 타입을 넣을수 있는 any라는 타입이 있습니다. 이는 Generic과 유사해보이긴 하나 타입을 any로 받을수 있기떄문에 타입을 보장받는 Generic과는 차이점이 있습니다.
아래의 코드로 예를 들겠습니다.
function checkNotNullAny(arg: any | null): any {
if (arg == null) {
throw new Error("not valid number");
}
return arg;
}
arg로 받는 인자가 null이라면 에러를 띄워주고 그외에는 arg값을 받아주는 checkNotNullAny라는 함수가 있습니다.
이는 arg로 어떤 타입이던 넣을수 있으나 return받는 타입역시 any로 찍힙니다.
하지만 Generic을 사용해서 예를 들겠습니다.
function checkNotNullGeneric<T>(arg: T | null): T {
if (arg == null) {
throw new Error("not valid number");
}
return arg;
}
여기에 어떤 인자로 넣던지 상관없고 심지어 아래 사진처럼 넣은 타입의 타입을 보장받을수 있습니다.
그리고 위의 사진처럼 타입을 따로 지정해주지 않아도 우리의 타입스크립트가 멋지게 타입을 추론해서 number라고 명시해주고 아래 사진처럼 타입을 지정해줘도 됩니다.
Class에서도 Generic을 사용가능하고 아래 코드로 예시들겠습니다.
interface Either<L, R> {
left: () => L;
right: () => R;
}
class SimpleEither<L, R> implements Either<L, R> {
constructor(private leftValue: L, private rightValue: R) {}
left(): L {
return this.leftValue;
}
right(): R {
return this.rightValue;
}
}
const either = new SimpleEither(4, 5);
console.log(either.left(), either.right());
either라는 interface를 implement한 SimpleEither는 L과 R이라는 Generic인자를 받습니다. 이제 새로운 either라는 변수로 SimpleEither라는 클래스를 받아오고 4,5를 넣고 그걸 콘솔로 띄워주면 아래와같이 멋지게 number로 나오는 걸 볼 수 있습니다.
여기에 들어가는 L과 R의 값으로 다른 타입을 넣어줘도 잘 나옵니다.
이처럼 Generic은 어떤 타입이던 들어올수 있지만 그에따른 타입을 보장받을수 있는 장점이 있어 유용하다고 생각합니다.
그리고 any와는 다르게 Generic을 사용하면 관련 메서드의 힌트를 완성할수 있었습니다.