
우리가 자주볼 수 있는 구문입니다. “엥? 나는 저런거 본 적없어요!” 라고 하신다면 아직 늦지 않았습니다!
node_modules
에 있는 아무 라이브러리를 찾아서 d.ts나 타입 지정된 곳을 가면 쉽게 볼 수 있을겁니다.이게 뭘까요?? 이건 뭔데 이렇게 쓰고 우리가 자주 사용하는 type지정, Interface, type과 다른점은 뭘까요?
declare가 뭐지?
그래서 declare는 무엇인가 하면,
declare
키워드는 변수의 값을 정의하지 않고 변수의 타입을 지정할 때 사용되는 주변 선언에서 사용되며, 이러한 선언은 TypeScript에 정의된 항목이 코드 어딘가에 존재한다고 알려주는 역할을 합니다.- 주 목적: JavaScript 환경에 존재하는 값이나 객체, 함수 등의 타입을 선언합니다. 주로 외부 라이브러리나 글로벌 변수에 대한 타입을 정의할 때 사용됩니다.
- 특징:
declare
는 코드에 실제로 존재하는 객체나 값의 구현을 정의하는 것이 아니라, 그 존재와 형태만을 TypeScript에 알려주는 역할을 합니다.
그럼 다른 타입 지정할때 사용하는 type과 interface는 어떤 특징이 있을까요?
declare let globalValue: string; // 글로벌 변수의 타입만을 선언합니다.
type
- 주 목적: 기존 타입을 기반으로 새로운 타입을 정의합니다. 유니온(union), 인터섹션(intersection)과 같은 복잡한 타입 조합을 표현할 때 유용합니다.
- 특징: 객체 리터럴의 형태로도 타입을 정의할 수 있지만,
interface
보다는 기능적으로 제한적입니다.
type User = { name: string; age: number; }; type Status = "active" | "inactive";
interface
- 주 목적: 객체의 구조나 클래스, 함수 등의 형태를 정의하는 데 사용됩니다. 확장성이 좋아서 모듈화된 타입 정의에 적합합니다.
- 특징:
interface
는 확장이 용이하며, 동일한 이름의interface
를 여러 번 선언하면 자동으로 합쳐집니다 (declaration merging).
interface Person { name: string; age: number; } // 나중에 확장 interface Person { address: string; }
정리하자면
declare
: 실제 구현이 없이 타입만 선언합니다.
type
: 복잡한 타입 조합을 위한 타입 별칭을 정의합니다.
interface
: 객체의 구조를 정의하며 확장성이 뛰어납니다.
다만, 실제 개발에서는
type
과 interface
의 선택은 프로젝트의 요구 사항, 팀의 스타일 가이드, 그리고 개인의 취향에 따라 다를 수 있습니다.declare의 다양한 사용법
기본 선언
TypeScript 코드 외부에 존재하는 변수의 타입을 지정하기 위해
declare
키워드를 사용할 수 있습니다.declare let someExternalVariable: string; // 사용법 console.log(someExternalVariable);
모듈 선언
declare
를 사용하여 외부 모듈의 형태를 설명할 수 있습니다.// 파일: my-module.d.ts declare module 'my-module' { export function foo(): string; } // 다른 파일에서의 사용 import { foo } from 'my-module'; console.log(foo());
전역 변수 선언
전역 변수 (
window
객체와 같은)를 다룰 때 declare
키워드를 다음과 같이 사용할 수 있습니다.declare global { interface Window { myGlobalVariable: number; } } // 사용법 window.myGlobalVariable = 42; console.log(window.myGlobalVariable);
타입 및 인터페이스 선언
외부 라이브러리에서 예상할 수 있는 사용자 지정 타입이나 인터페이스를 선언하는 것이 일반적입니다.
declare type CustomResponse = { data: any; status: 'success' | 'error'; };
클래스 선언
메서드를 구현하지 않고 클래스의 타입을 선언할 수도 있습니다.
declare class MyLibrary { constructor(options: { a: number, b: string }); myMethod(): void; }
위의 예시들처럼 선언을 할 수 있습니다. 그렇다면 declare를 왜 사용하는 걸까요?
- 호환성: TypeScript 코드가 타입 오류 없이 JavaScript 라이브러리와 상호 운용되게 합니다.
- 안전성: 정확한 타입 선언을 제공함으로써 런타임 전에 잠재적인 타입 오류를 포착할 수 있습니다.
- 문서화: 타입 선언은 라이브러리 함수와 변수에서 기대할 수 있는 타입을 알려주는 문서의 형태로 작동합니다.
이런식으로 TypeScript에서,
declare
키워드는 정적으로 타입이 지정된 TypeScript와 동적 JavaScript 사이의 격차를 해소하는 데 중요한 역할을 합니다. declare
를 이해하고 활용함으로써 외부 JavaScript 라이브러리와 런타임 환경과의 상호작용 중 타입 안전성을 보장할 수 있습니다.런타임 전에 문제를 파악하며 좀 더 완성도 있는 코드를 작성할 수 있도록 항상 생각하면서 개발해야 할 것 같네요.. 오늘도 감사합니다.