개발새발
타입도 상속이 가능하다 본문
JavaScript에서는 class 문법을 통해 객체 간 상속이 가능하다. 마찬가지로 TypeScript에서도 타입끼리 상속(확장) 하여 중복 없이 타입을 재사용할 수 있다.
자바스크립트에서의 상속: 클래스 예시
class Animal {
constructor(name) {
this.name = name;
}
}
class Dog extends Animal {
bark() {
console.log(`${this.name} 멍멍`);
}
}
class Cat extends Animal {
meow() {
console.log(`${this.name} 야옹`);
}
}
Dog와 Cat 클래스는 Animal 클래스를 상속받기 때문에 name 속성을 중복해서 작성하지 않아도 된다.
TypeScript에서의 상속: interface + extends
interface Animal {
name: string;
}
interface Dog extends Animal {
bark(): void;
}
interface Cat extends Animal {
meow(): void;
}
- Dog와 Cat은 Animal 타입을 상속받아 name 속성을 자동으로 포함한다.
- 중복된 속성을 반복해서 쓰지 않아도 되어 코드의 유지보수가 쉽다.
타입 별칭(type)도 상속처럼 확장 가능
type Animal = {
name: string;
};
type Dog = Animal & {
bark(): void;
};
type Cat = Animal & {
meow(): void;
};
type Name = Cat['name']; // string
- & 연산자를 사용해 타입을 교집합(intersection) 으로 결합하면 확장과 유사한 효과를 얻을 수 있다.
- Cat 타입은 Animal의 name 속성을 상속하게 된다.
| (유니언) 연산자와의 차이점
type Dog = Animal | { bark(): void }; // ❌
- | 연산자는 합집합(union) 을 의미한다.
- Dog 타입은 Animal 타입이거나 { bark(): void } 타입일 수 있기 때문에, name 속성이 없을 수도 있는 타입이 되어 Cat['name']처럼 속성 접근 시 에러가 발생한다.
- 상속처럼 사용하고 싶으면 & 을 사용하자.
interface와 type 간에도 상호 확장 가능
type Animal = { name: string };
interface Dog extends Animal {
bark(): void;
}
interface Cat extends Animal {
meow(): void;
}
type Name = Cat['name']; // string
- type이 정의한 타입을 interface가 extends할 수 있다.
- 반대로 interface 타입을 type에서 & 연산자로 확장하는 것도 가능하다.
다중 상속도 가능하다
interface Dog extends Animal {
bark(): void;
}
interface Cat extends Animal {
meow(): void;
}
interface DogCat extends Dog, Cat {}
type MeowFn = DogCat['meow']; // () => void
type BarkFn = DogCat['bark']; // () => void
- DogCat은 Dog와 Cat을 동시에 상속하여, bark와 meow를 모두 사용할 수 있는 타입이 된다.
- TypeScript는 다중 상속을 지원하며, 모든 부모 타입의 속성과 메서드를 합쳐 하나의 타입으로 생성한다.
속성 타입 변경도 가능하다 (단, 호환성 유지 필수)
interface Merge {
one: string;
two: string;
}
interface Merge2 extends Merge {
one: 'h' | 'w'; // ✅ string의 하위 타입이므로 가능
two: '123'; // ✅ string의 하위 타입이므로 가능
}
하지만 아래처럼 전혀 다른 타입으로 변경하려 하면 오류가 발생한다.
interface Merge2 extends Merge {
two: 123; // ❌ number는 string에 대입 불가
}
자식 타입에서 부모 속성을 override 할 수는 있지만, 대입 가능성(subtyping) 을 만족해야 한다.
실무에서의 활용 포인트
공통 속성 묶기
interface BaseUser {
id: string;
createdAt: Date;
}
interface AdminUser extends BaseUser {
role: 'admin';
}
interface NormalUser extends BaseUser {
role: 'user';
}
교차 타입으로 기능 확장
type WithMeta = {
metadata: Record<string, any>;
};
type EnrichedUser = BaseUser & WithMeta;
개념 | 문법 | 설 |
타입 상속 (interface) | interface A extends B | interface 간 상속 |
타입 확장 (type) | type A = B & C | type 간 확장 |
interface ← type 확장 | interface A extends TypeAlias | 가능 |
type ← interface 확장 | type A = Interface & {} | 가능 |
다중 상속 | interface A extends B, C | 여러 타입 동시에 확장 |
속성 override 조건 | 서브타입 관계 만족 시 가능 | 상속한 타입보다 좁아야 함 |
'Typescript' 카테고리의 다른 글
조건문과 비슷한 컨디셔널 타입이 있다 (0) | 2025.03.29 |
---|---|
객체 간에 대입할 수 있는지 확인하는 법을 배우자 (0) | 2025.03.22 |
타입을 집합으로 생각하자 (유니언, 인터섹션) (0) | 2025.03.22 |
객체의 속성과 메서드에 적용되는 특징을 알자 (0) | 2025.03.22 |
인터페이스로 객체를 타이핑하자 (0) | 2025.03.16 |