
제네릭은 타입을 미리 정의하지 않고 사용하는 시점에 원하는 타입을 정의해서 쓸 수 있는 문법입니다.
재사용 가능한 컴포넌트를 만들기 위해 타입스크립트에서 사용하는 도구 중 하나는 제네릭입니다. 즉, 단일 타입이 아닌 다양한 타입에서 작동하는 컴포넌트를 작성할 수 있습니다.
사용자는 제네릭을 통해 여러 타입의 컴포넌트나 자신만의 타입을 사용할 수 있습니다.
function getText(text: any): any {
return text;
}
위의 코드를 살펴보면,
getText 함수는 텍스트를 인수로 넣으면 그대로 반환하는 함수입니다.any 타입을 사용하면 인수의 타입이 어떤 타입이든 상관 없다는 뜻입니다.function getText<Type>(text: Type): Type {
return text;
}
Type은 사용자가 준 인수의 타입을 캡처하고, 인수와 반환 타입을 같은 타입을 사용할 수 있도록 해줍니다.getText 함수를 실행할 때 아무 타입이나 넘길 수 있습니다.getText<string>('hi'); // higetText 함수에 string 타입을 할당한 코드입니다. getText 함수에서 Type 타입 변수가 선언된 곳에 모두 들어갑니다.// 이 함수는 아래처럼 동작합니다.
function getText<string>(text: string): string {
return text;
}
function getText(text: string): string {
return text;
}getText('hi');<>)에 담아 명시적으로 전달하지 않아도 값 'hi'의 타입을 추론하여 Type 타입 변수에 전달해줍니다.function getText(text: string): string {
return text;
}
function getNumber(num: number): number {
return num;
}
위의 코드를 살펴보면,
getText 함수는 문자열 타입의 텍스트를 인수로 받아 그대로 반환합니다.getNumber 함수는 숫자 타입의 텍스트를 인수로 받아 그대로 반환합니다.any 타입을 사용할 수도 있습니다.function getText(text: any): any {
return text;
}
any 타입을 사용하면 타입을 다양하게 받을 수 있고 코드의 중복을 제거할 수 있습니다.any를 사용하면 타입스크립트의 장점인 에러 사전 방지가 무색해 질 수 있습니다.function getText<T>(text: T): T {
return text;
}
getText<string>('hi'); // hi
getText<number>(100); // 100
interface Product {
value: string;
selected: boolean;
}
interface Stock {
value: number;
selected: boolean;
}
위의 코드를 살펴보면,
interface Shoppingmall<T> {
value: T;
selected: boolean;
}
// 인터페이스를 각각 작성
const product: Product;
const stock: Stock;
const address: Address;
// 하나의 제네릭 인터페이스 작성
const product: Shoppingmall<string>;
const stock: Shoppingmall<number>;
const address: Shoppingmall<{ city: stirng; zipCode: string }>;
class GetNumber<T> {
value: T;
add: (x: T, y: T) => T;
}
let num = new GetNumber<number>();
num.value = 10;
num.add = function (x, y) {
return x + y;
}
위의 코드를 살펴보면,
GetNumber 클래스에는value와 add 속성이 있습니다. value와 add 속성은 모두 넘겨 받은 타입을 사용합니다.number 타입으로 선언하였기 때문에 value와 add 속성은 number 타입이 됩니다.add는 함수이므로, x와 y 인자 그리고 반환값이 모두 number 타입으로 선언됩니다.function getText<T>(text: T): T {
return text;
}
getText<string>('hi'); // hi
getText<number>(100); // 100
getText<boolean>(true); // true
위의 코드를 살펴보면,
getText 함수는 제네릭을 이용하여 여러 타입을 받을 수 있는 함수입니다. extends 키워드를 사용하여 타입을 제약할 수 있습니다.function getText<T extends { length: number }>(text: T): T {
return text.length;
}
getText('hi'); // 2
getText([1, 2, 3]); // 3
getText({ title: 'abc', length: 123 }); // 123
getText(10); // Error
extends 키워드로 length 속성을 갖는 타입만 받도록 제약하였습니다.type Developers = keyof { name: string; skill: string; }
// type Developers = "name" | "skill"
위의 코드를 살펴보면,
keyof 키워드는 특정 타입의 키 값을 추출해서 문자열 유니언 타입으로 변환해 줍니다.Developers 타입 별칭에 객체의 키인 name과 skill이 유니언 타입으로 선언되었습니다.Developers 타입 별칭은 name이나 skill 타입을 가집니다.function printKeys<T extends keyof { name: string; skill: string; })>(value: T) {
console.log(value);
}
printKeys('name'); // name
printKeys('skill'); // skill
printKeys('address'); // Error
printKeys(100); // Error
위의 코드를 살펴보면,
extends 키워드와 keyof 키워드를 조합하여 name이나 skill 타입만을 받도록 제약하였습니다.name이나 skill 문자열 이외의 문자열이나 타입을 넘기면 에러가 발생합니다.참고
📖 쉽게 시작하는 타입스크립트
🔗https://www.typescriptlang.org/docs/handbook/2/generics.html#handbook-content