고급 TypeScript - 고급 타입: 제네릭 타입
고급 타입: 제네릭 타입
제네릭 타입은 TypeScript에서 타입의 재사용성을 극대화하고, 코드의 유연성과 안전성을 높이는 데 중요한 역할을 합니다. 제네릭은 특정 데이터 유형에 국한되지 않고 다양한 데이터 유형에 대해 작동할 수 있는 함수나 클래스를 정의할 수 있게 해줍니다. 이를 통해 코드 중복을 줄이고, 더 가독성이 좋은 코드를 작성할 수 있습니다.
1. 제네릭의 기본 개념
제네릭을 사용하면 함수나 클래스가 호출될 때 실제로 사용할 데이터 유형에 따라 동적으로 타입이 결정됩니다. 예를 들어, 배열이나 리스트와 같은 컬렉션 구조체를 만들 때 특히 유용합니다.
예시:
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("Hello World"); // output의 타입은 string
let numberOutput = identity<number>(42); // numberOutput의 타입은 number
위 예시에서 identity
함수는 입력된 인자의 데이터 유형(T)에 따라 반환되는 값의 데이터 유형도 동일하게 유지됩니다.
2. 제네릭 인터페이스
제네릭 인터페이스를 사용하면 복잡한 객체 구조에서도 여러 가지 형태를 지원하는 강력한 도구가 됩니다. 이러한 방식으로 작성된 인터페이스는 다양한 상황에서 재사용될 수 있습니다.
예시:
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity; // myIdentity는 숫자형만 허용됨
여기서 GenericIdentityFn
이라는 인터페이스는 어떤 종류의 데이터를 받아들이고 그 데이터를 반환하는 함수를 정의합니다.
3. 제네릭 클래스
제네릭 클래스 또한 매우 유용하며, 객체 지향 프로그래밍 패러다임과 잘 어울립니다. 이는 상태(state)와 메서드(method)를 갖춘 클래스를 다양한 데이터 형식으로 생성할 수 있게 합니다.
예시:
class Box<T> {
private contents: T;
constructor(value: T) {
this.contents = value;
}
getContents(): T {
return this.contents;
}
}
let boxOfStrings = new Box<string>("Hello");
console.log(boxOfStrings.getContents()); // "Hello"
let boxOfNumbers = new Box<number>(123);
console.log(boxOfNumbers.getContents()); // 123
위 예시는 Box
라는 클래스를 통해 문자열과 숫자를 각각 저장하고 꺼내오는 방법을 보여줍니다.
4. 다중 제너릭 파라미터
때때로 하나 이상의 제너릭 파라미터가 필요할 수도 있습니다. 이 경우에도 간단하게 구현할 수 있습니다.
예시:
function pair<K, V>(key: K, value: V): [K, V] {
return [key, value];
}
const keyValuePair = pair<string, number>('age', 30);
console.log(keyValuePair); // ['age', 30]
여기서는 키와 값을 쌍으로 묶어주는 pair
함수를 만들어 두 개의 서로 다른 타입(K와 V)을 받아들입니다.
결론
제네릭 타이핑 기술은 TypeScript에서는 매우 강력하고 유용한 기능입니다. 이를 활용함으로써 개발자는 더욱 견고하고 확장 가능한 코드를 작성할 수 있으며, 코드베이스 내에서 일관성을 유지하면서도 다양한 요구 사항을 충족시키는 것이 가능합니다.