프로그래밍Typescript 개발자

TypeScript의 Declaration Merging 메커니즘에 대해 설명해 주세요. 인터페이스, 함수 및 네임스페이스에 대해 어떻게 작동하며, 여기에는 어떤 함정이 있나요?

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

답변.

Declaration Merging (선언 병합) 은 TypeScript의 고유한 메커니즘으로, 동일한 이름의 선언을 단일 타입/실체로 결합할 수 있습니다. 이는 인터페이스, 네임스페이스 및 함수에 대해 작동합니다.

  1. 인터페이스: 동일한 이름의 인터페이스 선언이 하나의 큰 인터페이스로 병합됩니다:
interface User { name: string; } interface User { age: number; } const u: User = { name: 'Vasya', age: 42 }; // OK
  1. 함수 + 네임스페이스: 동일한 이름의 함수와 네임스페이스가 병합되어 정적 메서드가 집계됩니다:
function helper() {} namespace helper { export function extra() {} } helper.extra(); // OK
  1. 네임스페이스 + enum 및 네임스페이스 + class: 정적 속성으로 클래스 및 enum 확장을 위해 병합이 가능합니다.

트릭 질문.

인터페이스의 서로 다른 공간에서 동일한 이름의 메서드가 병합될 때 어떻게 되며, 시그니처가 다를 경우 어떻게 되나요?

답변:

서로 다른 병합 인터페이스에서 동일한 이름의 메서드를 선언하면, TypeScript는 최종 인터페이스에서 이러한 메서드를 "오버로드"하려고 합니다. 그러나 시그니처가 호환되지 않으면 (오버로드가 불가능한 경우) 컴파일 오류가 발생합니다.

예:

interface Foo { bar(a: number): void } interface Foo { bar(a: string): void } // OK: 오버로드 interface Foo { bar(a: number[]): void } // 오류: 호환되지 않는 시그니처

주제에 대한 잘못된 이해로 인한 실제 오류 사례


이야기

하나의 프로젝트에서 여러 기능을 위해 declaration merging을 통해 외부 인터페이스 Window를 확장했습니다: 한 팀은 window.myFeature: boolean을 추가하고, 다른 팀은 window.myFeature: number를 추가했습니다. 병합으로 인해 타입 오류가 발생했고, 컴파일러는 전체 집합 시점에만 충돌을 잡았습니다 — 누군가는 빠르게 이름을 변경해야 했습니다.


이야기

두 개의 서로 다른 메서드 시그니처의 ArrayHelper 인터페이스를 잘못 선언하여 "두 가지 옵션이 모두 사용 가능"하다고 예상했습니다. 실제로 첫 번째 시그니처가 두 번째를 덮어쓰게 되어 IDE에서 잘못된 자동 완성이 발생하고 새 모듈과 통합하는 중에 버그가 발생했습니다.


이야기

declaration merging을 통해 함수에 대해 "확장"을 사용하면서 개발자가 네임스페이스 내부에서 export를 잘못 선언하여 함수가 액세스할 수 없게 되었습니다. 리뷰 후, 올바른 export 없이는 병합이 작동하지 않으며 속성이 함수에 나타나지 않는다는 것을 알게 되었습니다.