타입스크립트를 사용하면서 제네릭에서 사용하는 extends와 인터페이스에서 사용하는 extends의 개념이 다르다는 점을 알고는 있었지만, 시간이 부족한다는 핑계로 자세히 알아보지 못한 것을 반성하며, 이에 대해 좀 더 자세히 알아보기로 마음먹었습니다.
지속적인 학습을 통해 더 나은 개발자로 성장하고자 하는 마음으로 글을 남깁니다. 🙏
제네릭에서의 extends
제네릭에서 extends 키워드는 타입 매개변수의 상한 경계(upper bound)를 지정하는 데 사용됩니다. 상한 경계는 특정 타입으로 제한하여 제네릭 타입이 해당 타입을 상속받거나 해당 인터페이스를 구현해야 한다는 제약을 설정합니다. 예를 들어, <T extends SomeClass>와 같이 사용하여 타입 변수 T가 SomeClass를 상속받는 클래스일 수 있도록 제한할 수 있습니다.
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
}
class Cat extends Animal {
meow(): void {
console.log("Meow!");
}
}
class Dog extends Animal {
bark(): void {
console.log("Woof!");
}
}
function animalSound<T extends Animal>(animal: T): void {
console.log(`${animal.name} makes a sound.`);
}
const cat = new Cat("Whiskers");
const dog = new Dog("Buddy");
animalSound(cat); // 출력: Whiskers makes a sound.
animalSound(dog); // 출력: Buddy makes a sound.
위 예제에서 animalSound 함수는 제네릭 타입 T를 사용하고, T가 Animal 클래스를 상속받는 타입으로 제한합니다. 이를 통해 animalSound 함수는 Animal 클래스 또는 그를 상속받은 하위 클래스의 인스턴스를 인자로 받을 수 있습니다. 따라서 animalSound(cat)와 animalSound(dog) 호출이 가능하며, 각각 해당 객체의 이름을 출력하는 동작을 수행합니다.
인터페이스에서의 extends
인터페이스에서 extends 키워드는 인터페이스 상속을 통해 다중 상속을 지원하는 데 사용됩니다. 인터페이스 A가 인터페이스 B를 extends 할 경우, 인터페이스 A는 인터페이스 B의 멤버를 상속받습니다. 이를 통해 코드 재사용성과 계약(contract)의 구현을 강화할 수 있습니다. 예를 들어, interface A extends B와 같이 사용하여 인터페이스 A가 인터페이스 B를 확장한다고 선언할 수 있습니다.
interface Shape {
calculateArea(): number;
}
interface Rectangle extends Shape {
width: number;
height: number;
}
class Square implements Shape {
sideLength: number;
constructor(sideLength: number) {
this.sideLength = sideLength;
}
calculateArea(): number {
return this.sideLength ** 2;
}
}
function printArea(shape: Shape): void {
console.log(`Area: ${shape.calculateArea()}`);
}
const rectangle: Rectangle = {
width: 5,
height: 3,
calculateArea(): number {
return this.width * this.height;
}
};
const square = new Square(4);
printArea(rectangle); // 출력: Area: 15
printArea(square); // 출력: Area: 16
위 예제에서 Shape 인터페이스는 calculateArea 메서드를 가지고 있습니다. Rectangle 인터페이스는 Shape 인터페이스를 확장하여 멤버를 상속받습니다. 따라서 Rectangle 인터페이스는 calculateArea 메서드를 구현해야 합니다.
Square 클래스는 Shape 인터페이스를 구현하고 있으며, calculateArea 메서드를 재정의하여 네모난 도형의 넓이를 계산합니다.
printArea 함수는 Shape 인터페이스를 인자로 받아 해당 도형의 넓이를 출력합니다. 이를 통해 printArea(rectangle)과 printArea(square) 호출이 가능하며, 각각 해당 도형의 넓이를 출력하는 동작을 수행합니다.
요약
제네릭에서의 extends는 타입 매개변수의 상한 경계를 지정하는 데 사용되고, 인터페이스에서의 extends는 인터페이스 상속을 통한 멤버 상속을 나타내는 데 사용됩니다.
'기억보단 기록을 > Typescript' 카테고리의 다른 글
[Typescript] Section 12. Mapped Type (0) | 2023.05.21 |
---|---|
[Typescript] Section 11. 유틸리티 타입 (0) | 2023.05.21 |
[Typescript] Section 10. 타입추론 (0) | 2023.05.20 |
[Typescript] Section 09. 제네릭 (0) | 2023.05.20 |
[Typescript] Section 08. Class (0) | 2023.05.20 |