TypeScript
TypeScript 제네릭
honey.kikiki
2021. 10. 16. 16:31
728x90
타입스크립트 제네릭
클래스나 함수의 목적중 하나는 '재사용성'에 있습니다. 이 제네릭을 이용하게되면 재사용성이 한층 더 증가합니다. 일종의 '틀' 이라고 생각하시면 됩니다. 타입스크립트에서 제네릭을 어떻게 쓰는지에대해 알아보도록 하겠습니다.
클래스에서의 제네릭
class NumberButton {}
class TextButton {}
class OprButton {}
class ButtonContainer<T> {
private container: T[];
getButton(index: number) {
return this.container[index];
}
// ...
}
const numberContainer = new ButtonContainer<NumberButton>();
const textContainer = new ButtonContainer<TextButton>();
const oprContainer = new ButtonContainer<OprButton>();
제너릭의 중요한 부분이 <T> 입니다. type 의 약자로 보통 T 를 쓰지만 변경할 수 있습니다. type 에서 따왔듯이 타입에따라 틀이 바뀐다는 점입니다.
생성할때도 마찬가지로 () 전에 <> 꺾쇠괄호 안에 타입을 주입합니다.
함수에서의 제네릭
function getFirst(array: any[]): any {
return array[0];
}
다음코드는 배열의 첫번째 요소를 반환하는 코드입니다. any를 사용한것을 볼 수 있는데 이것을 제네릭으로 바꿔보겠습니다.
function getFirst<T>(array: T[]): T {
return array[0];
}
함수의 이름 뒤에 <T> 가 들어간것을 확인할 수 있습니다. 그리고 호출할 때도 타입을 정해줍니다.
getFirst<number>([1, 2, 3]);
getFirst<string>(['h','e','e']);
제약조건
제네릭을 이용하였지만 해당 프로퍼티가 있는지 없는지에 대해 확신할 수 없습니다. 그래서 컴파일러는 다음 코드에 대해 에러를 뱉습니다.
function getHeight<T> (person: T) {
return person.height; // Error!
// TS2339: Property 'height' does not exist on type 'T'.
}
이 코드는 개발자 입장에서는 person 이 들어옴을 확신하고 작성했지만 컴파일러에서는 .height라는 프로퍼티가 있는지 없는지 알 수 없기 때문에 생긴 에러입니다. 때문에 컴파일러에게 확신을 주게끔 인터페이스를 생성해주고 extends 키워드로 제약조건을 만들어줍니다.
interface Heightwise {
height: number;
}
function getHeight<T extends Heightwise> (person: T) {
return person.height;
}
const myInfo = {
name: 'kikiki',
height: 171,
};
console.log(getHeight(myInfo)); // 171