개발새발
앰비언트 선언도 선언 병합이 된다 본문
타입스크립트는 자바스크립트 위에 얹힌 정적 타입 시스템이다. 그렇기 때문에 자바스크립트 생태계에 존재하는 수많은 외부 라이브러리들과의 호환성을 고려해야 한다. 특히, 타입 정보가 제공되지 않는 자바스크립트 코드에 타입을 추가해야 할 때 유용한 개념이 바로 앰비언트 선언이다.
또한, 타입스크립트는 동일한 이름을 가진 선언을 병합할 수 있는 강력한 기능도 제공한다. 이 글에서는 앰비언트 선언과 선언 병합이 어떻게 동작하며, 실제로 어떻게 활용할 수 있는지에 대해 설명한다.
1. 앰비언트 선언 (Ambient Declarations)
1.1 앰비언트 선언이란?
외부 자바스크립트 코드에 타입 정보를 부여하고자 할 때 사용하는 것이 앰비언트 선언이다. declare 키워드를 사용하여 타입만 정의하고 구현부는 생략한다. 이 선언은 실제 구현이 외부에 존재한다고 타입스크립트가 믿도록 하는 장치이다.
declare namespace NS {
const v: string;
}
declare enum Enum {
ADMIN = 1,
}
declare function func(param: number): string;
declare const variable: number;
declare class C {
constructor(p1: string, p2: string);
}
// 타입스크립트 입장에서는 문제가 없다
new C(func(variable), NS.v);
주의: declare로 선언한 값이 런타임에 실제로 존재하지 않으면 실행 에러가 발생한다.
1.2 왜 namespace, enum에 declare를 붙이는가?
- declare namespace는 내부 멤버 구현 없이 타입만 제공할 수 있게 해준다.
- declare enum은 컴파일 시 실제 자바스크립트 코드가 생성되지 않도록 한다.
declare namespace Lib {
function doSomething(): void;
}
declare enum LogLevel {
DEBUG,
INFO,
ERROR,
}
1.3 인터페이스와 타입은 declare가 필요할까?
declare interface I {}
declare type T = number;
- 위처럼 declare로 선언할 수 있으나, 사실 생략해도 동일하게 작동한다.
- 이유는 인터페이스와 타입 별칭은 타입 정보만 포함되기 때문이다.
2. 선언 병합 (Declaration Merging)
타입스크립트는 특정 타입 선언끼리 자동으로 병합하는 기능을 제공한다. 예를 들어 interface, namespace, function은 같은 이름으로 여러 번 선언되어도 자동으로 합쳐진다.
2.1 병합 가능한 선언 조합
선언 | 네임 스페이스 | 클래스 | enum | 인터페이스 | 타입 별칭 | 함수 | 변수 |
네임스페이스 | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
클래스 | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
인터페이스 | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
함수 | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
→ 널리 알려진 조합:
- interface + interface → 속성 병합
- namespace + namespace → 멤버 병합
- function + namespace → 함수에 속성 부여
3. 실제 선언 병합 예시
3.1 클래스 + 함수 병합
declare class A {
constructor(name: string);
}
function A(name: string) {
return new A(name);
}
new A('sunho'); // OK
A('sunho'); // OK
- declare class A는 타입만 정의
- function A는 실제 구현을 제공
- new A()와 A() 둘 다 사용 가능
3.2 함수 + 네임스페이스 병합
자바스크립트에서는 함수도 객체이므로 속성을 가질 수 있다. 타입스크립트는 이를 반영해, 함수와 네임스페이스를 병합할 수 있도록 지원한다.
function Ex() {
return 'hello';
}
namespace Ex {
export const a = 'world';
export type B = number;
}
Ex(); // hello
Ex.a; // world
const b: Ex.B = 123;
이 방식은 라이브러리 형태의 API에서 자주 활용된다. 예: jQuery(), jQuery.ajax 처럼 함수와 속성이 함께 있는 경우.
4. 결론
- 앰비언트 선언은 외부 JS 코드에 타입 정보를 추가할 때 필수적인 장치이다.
- 선언 병합은 함수, 인터페이스, 네임스페이스 등에 동일한 이름으로 기능을 확장할 수 있게 해준다.
- 선언 병합은 강력하지만 복잡할 수 있으므로, interface, namespace, function에서만 주로 활용하고, 나머지는 이름 충돌을 피하는 것이 안전하다.
기능 | 목적 | 주의 사항 |
declare | 구현 없이 타입만 선언 | 반드시 실제 런타임 값이 존재해야 함 |
선언 병합 | 여러 선언을 하나로 합침 | 병합 가능한 조합만 사용해야 함 |
function + ns | 함수에 타입 정보나 속성 추가 | 객체처럼 함수 사용 가능 |
'Typescript' 카테고리의 다른 글
Exclude, Extract, Omit, NonNullable (0) | 2025.04.12 |
---|---|
Partial, Required, Readonly, Pick, Record (0) | 2025.04.12 |
함수에 기능을 추가하는 데코레이터 함수가 있다 (0) | 2025.04.11 |
타입스크립트의 에러 코드로 검색하자 (0) | 2025.04.11 |
배운 것을 바탕으로 타입을 만들어보자 (0) | 2025.04.11 |