프로그래밍풀스택 개발자

타입 확장의 작동 방식(extends)은 무엇이며, 타입 및 인터페이스에서 사용하는 데 어떤 신경을 써야 할까요? 그리고 이것이 프로젝트 구조에 어떻게 영향을 미칠까요?

Hintsage AI 어시스턴트로 면접 통과

답변

TypeScript에서 타입을 확장(상속)하는 방법은 interface extendstype & type(교차 타입)을 사용하는 것입니다. 또한 인터페이스는 타입을 확장할 수 있고, 그 반대도 가능합니다.

인터페이스는 속성을 상속하기 위해 extends 키워드를 사용합니다:

interface Animal { name: string; } interface Bird extends Animal { wings: number; }

타입&를 통해 결합될 수 있습니다:

type Animal = { name: string }; type Bird = Animal & { wings: number };

또한, 인터페이스는 다른 타입을 확장할 수 있습니다:

type Base = { id: number }; interface Derived extends Base { description: string; }

특징:

  • 인터페이스는 선언적 병합(declaration merging)을 지원하며, 타입은 그렇지 않습니다.
  • 라이브러리와 같은 다른 엔터티를 확장할 가능성이 있다면 인터페이스를 사용하는 것이 좋습니다.
  • 중첩된 extends는 복잡한 계층 구조를 일으켜 유지 보수를 어렵게 하고 이름 충돌을 발생시킬 수 있습니다.

질문의 함정

타입(type)은 인터페이스를 통해 확장하거나 그 반대가 가능한가요? 대부분의 사람들이 저지르는 실수는 무엇인가요?

많은 사람들은 인터페이스는 인터페이스를 통해서만 확장할 수 있다고 생각하지만, 실제로는 인터페이스가 타입을 확장할 수 있습니다:

type Basic = { flag: boolean }; interface Extra extends Basic { name: string; }

하지만 타입은 다른 타입을 extends로 확장할 수 없으며, 오직 교차 타입(&)을 통해서만 가능합니다.

실제 오류 사례


이야기

어떤 대규모 프로젝트에서 인터페이스를 extends를 통해 결합하면서, 동일한 이름을 가진 속성은 타입을 일치시켜야 한다는 것을 잊어버렸습니다. 누군가 부모 인터페이스의 속성 타입을 변경했을 때, 자식 인터페이스에서 silent conflict가 발생하여 데이터베이스가 API와 일치하지 않게 되었습니다.

이야기

어떤 라이브러리에서는 & (교차)를 통해 속성이 겹치는 type alias를 작성했지만, 몇몇 속성은 타입이 호환되지 않도록 만들었습니다. TypeScript는 컴파일 단계에서 이를 허용했지만, 실제 런타임에서는 시스템에 정의되지 않은 필드가 생겼습니다.

이야기

팀은 interface를 타입으로 확장할 수 없다고 생각하여, 공통 기능을 확장하기 위해 모든 구조를 type에서 interface로 다시 작성하는 데 많은 시간과 노력을 낭비했습니다. 그러나 실제로는 기존 타입을 비표준 방식으로 확장할 수 있었습니다.