.d.ts 파일 작성법
구현이 없는 d.ts 파일에 declare로 JavaScript 변수·함수·클래스의 공개 타입을 기술하고 컴파일러가 찾도록 배치합니다.
타입스크립트는 타입 추론을 통해 많은 타입 정보를 자동으로 얻어낼 수 있지만, 자바스크립트 코드(라이브러리, 프레임워크, 레거시 코드 등)를 타입스크립트 프로젝트에서 사용할 때는 타입 정보를 알 수 없는 경우가 발생합니다.
이럴 때 필요한 것이 바로 타입 선언 파일(Declaration Files), 즉 .d.ts 파일입니다.
.d.ts 파일은 실제 구현 코드 없이, 오직 타입 정보만을 담고 있는 파일입니다.
자바스크립트 코드가 외부에 공개하는 변수, 함수, 클래스 등의 설명서 역할을 하며, 타입스크립트 컴파일러는 이 .d.ts 파일을 참조하여 해당 자바스크립트 코드의 타입을 정확하게 이해하고 타입 검사를 수행합니다.
타입스크립트는 타입 추론을 통해 많은 타입 정보를 자동으로 얻어낼 수 있지만, 자바스크립트 코드(라이브러리, 프레임워크, 레거시 코드 등)를 타입스크립트 프로젝트에서 사용할 때는 타입 정보를 알 수 없는 경우가 발생합니다. 이럴 때 필요한 것이 바로 타입 선언 파일(Declaration Files), 즉 .d.ts 파일입니다.
- .d.ts 사용 기준
구현 파일이 JavaScript뿐이거나 외부 라이브러리가 타입을 제공하지 않을 때 .d.ts로 공개 API의 타입 표면을 보강합니다. 타입 선언 파일(Declaration Files)
- .d.ts 파일의 기본 구조와 declare 키워드
.d.ts 파일은 .ts 파일과 거의 동일한 문법을 사용하지만, declare 키워드로 런타임 구현이 아니라 타입 선언만 제공한다는 뜻을 컴파일러에 알립니다. .d.ts 파일
- .d.ts 파일 작성 팁
외부에 노출되는 함수, 클래스, 상수만 선언하고 내부 helper까지 넓히지 않아야 구현 변화에 덜 흔들립니다. 설명서
- .d.ts 파일 작성법 기준
정확성 타입 선언 파일(.d.ts)은 JavaScript 구현의 공개 API를 타입으로 표현해 import한 코드가 컴파일 단계에서 검사되게 합니다. 비용 선언 파일이 구현과 어긋나면 컴파일은 통과해도 런타임 호출이 실패할 수 있으므로 사용 예시로 함께 검증해야 합니다. 확장성 선언 파일은 JavaScript 구현의 모듈 경계와 overload, namespace, global augmentation을 타입 시스템에 연결합니다. 예외 DefinitelyTyped의 @types 패키지가 있으면 직접 선언 파일을 만들기 전에 버전 호환성과 export 형태를 먼저 확인합니다.
- 정확성 타입 선언 파일(.d.ts)
JavaScript 구현의 공개 API를 타입으로 표현해 import한 코드가 컴파일 단계에서 검사되게 합니다.
- 비용 선언 파일
구현과 어긋나면 컴파일은 통과해도 런타임 호출이 실패할 수 있으므로 사용 예시로 함께 검증해야 합니다.
- 확장성 선언 파일
JavaScript 구현의 모듈 경계와 overload, namespace, global augmentation을 타입 시스템에 연결합니다.
- 예외 DefinitelyTyped의 @types 패키지
있으면 직접 선언 파일을 만들기 전에 버전 호환성과 export 형태를 먼저 확인합니다.
왜 .d.ts 파일이 필요한가?
JavaScript 구현은 따로 있고, TypeScript는 .d.ts를 통해 함수와 객체의 사용법을 검사한다.
- Runtime JSRuntime JS 실제
실행되는 구현 파일
- .d.ts.d.ts 값의 타입
호출 계약만 선언
- ConsumerConsumer import 후 타입 검사
자동완성 사용
- Drift riskDrift risk 구현
선언이 어긋나면 런타임 오류 가능
| 기준 | 해석 |
|---|---|
| 라이브러리 | npm package가 types 필드로 선언 파일 제공 |
| 전역 API | ambient declaration으로 이름 설명 |
| 핵심 | 선언 파일은 실행 코드가 아니라 사용 설명서다 |
아래 다이어그램은 .d.ts 파일에서 declare var, declare function, declare module, 전역 확장 중 어떤 형태를 선택해야 하는지 판단하는 기준을 묶어 보여줍니다.
구현을 새로 만드는 문법이 아니다. 이미 존재하는 값에 어떤 경로로 접근하는지부터 확인한다.
- import 없이 전역에서 사용
declare const function / class 이름 하나로 바로 접근하는 전역 값 declare namespace LegacyChart.render 처럼 한 객체 아래 API가 모임 declare global 모듈 파일 안에서 Window 같은 전역 타입을 보강
- import 문으로 불러서 사용
declare module "pkg" JS 패키지의 named/default export 모양을 설명 declare module "*.png" 번들러가 처리하는 확장자의 결과 타입을 설명 생성된 index.d.ts TS 라이브러리는 declaration 빌드로 공개 API를 배포
.d.ts 파일이 필요한 주요 이유는 다음과 같습니다.
자바스크립트 라이브러리 사용: jQuery, Lodash, React 등 수많은 자바스크립트 라이브러리들은 .js 파일 형태로 배포됩니다.
타입스크립트 프로젝트에서 이들을 사용할 때, .d.ts 파일이 없으면 해당 라이브러리의 함수나 객체에 접근할 때 any 타입으로 간주되어 타입 검사의 이점을 누릴 수 없습니다.
레거시 자바스크립트 코드 연동: 기존에 작성된 자바스크립트 코드를 타입스크립트 프로젝트에 통합할 때, 명시적인 타입 정보를 제공하여 타입 안전성을 확보합니다.
타입스크립트 라이브러리 배포: 타입스크립트로 작성된 라이브러리를 배포할 때, .ts 파일은 .js 파일과 .d.ts 파일로 컴파일됩니다.
사용자는 .js 파일(실제 구현)과 .d.ts 파일(타입 정보)을 함께 받아 타입스크립트 환경에서 라이브러리를 안전하게 사용할 수 있습니다.
전역 변수/객체 선언: 브라우저 환경에서 window, document와 같이 전역 스코프에 존재하는 객체나 변수의 타입을 명시할 때 사용됩니다.
.d.ts 파일의 기본 구조와 declare 키워드
.d.ts 파일은 .ts 파일과 거의 동일한 문법을 사용하지만, declare 키워드를 사용하여 이것은 실제 구현이 아니라, 단지 타입 정보임을 선언하는 것을 명시합니다.
declare 키워드는 컴파일된 자바스크립트 코드에는 포함되지 않습니다.
주요 declare 사용 예시
declare var / declare let / declare const: 전역 변수를 선언합니다.
declare const MY_GLOBAL_CONFIG: {
apiUrl: string;
timeout: number;
};
declare let globalCounter: number;declare function: 전역 함수를 선언합니다.
declare function customLog(message: string): void;
declare function calculateSum(...numbers: number[]): number;declare class: 클래스를 선언합니다.
declare class MyEventEmitter<T> {
on(eventName: string, listener: (data: T) => void): void;
emit(eventName: string, data: T): void;
}declare enum: 열거형을 선언합니다. (자바스크립트 런타임에는 열거형이 없으므로 const enum처럼 사용될 때 유용)
declare enum StatusCode {
Success = 200,
NotFound = 404,
ServerError = 500
}declare namespace: 관련된 전역 변수, 함수, 클래스 등을 하나의 논리적인 그룹으로 묶습니다. (7장 3절 "네임스페이스" 참조)
declare namespace jQuery {
interface Event {
// ...
}
function ajax(url: string, settings?: any): JQueryPromise<any>;
const version: string;
}
declare var $: typeof jQuery; // $도 jQuery 네임스페이스와 동일한 타입을 가짐이 예시처럼 .d.ts 파일에서 declare namespace는 전역 스코프에 특정 이름을 가진 객체가 존재하며 그 안에 멤버들이 있음을 선언합니다.
declare module: 특정 경로 또는 모듈 이름을 가진 자바스크립트 모듈의 타입을 선언합니다.
-
ES 모듈/CommonJS 모듈의 타입 선언
my-custom-module.d.ts declare module 'my-custom-module' { export interface Options { debug: boolean; port: number; } export function init(options: Options): void; export const version: string; export default class Client { // default export constructor(apiUrl: string); getData(): Promise<any>; } }이 파일을 작성하면, 다른
.ts파일에서import { init } from 'my-custom-module';또는import Client from 'my-custom-module';와 같이 가져올 수 있게 됩니다. -
파일 확장자를 위한 모듈 선언: 웹팩과 같은 번들러를 사용할 때
.css,.png등 자바스크립트가 아닌 파일을import하는 경우가 있습니다. 이들에 대한 타입을 선언할 때도declare module을 사용합니다.image.d.ts declare module '*.png' { const content: string; // 이미지 파일은 URL 문자열로 로드된다고 가정 export default content; } declare module '*.svg' { import * as React from 'react'; export const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement> & { title?: string }>; const src: string; export default src; }이제
import myImage from './logo.png';와 같이 이미지 파일을 가져와도 타입 오류가 발생하지 않습니다.
.d.ts 파일 작성 팁
필요한 타입만 선언: .d.ts 파일은 실제 구현 코드를 포함하지 않으므로, 자바스크립트 코드가 외부에 노출하는 멤버들만 선언하면 됩니다.
내부적으로만 사용되는 변수나 함수는 선언할 필요가 없습니다.
가능한 한 구체적인 타입 사용: any 타입을 남용하지 않고, 가능한 한 정확하고 구체적인 타입을 사용하여 타입 안전성을 극대화해야 합니다.
제네릭, 유니온 타입, 인터섹션 타입 등을 적극적으로 활용하세요.
불필요한 export 피하기: .d.ts 파일이 모듈이 아닌 전역 타입 선언을 목적으로 한다면, 최상위 레벨에서 export를 사용하지 않아야 합니다.
export를 사용하면 해당 .d.ts 파일은 모듈로 간주됩니다.
- 전역 선언:
declare var $, declare function jQuery() - 모듈 선언:
declare module 'lodash' { export function ... }
자동 생성 활용: tsc --declaration 또는 tsc -d 옵션을 사용하면 타입스크립트 소스 코드로부터 .d.ts 파일을 자동으로 생성할 수 있습니다.
이를 기반으로 필요한 부분을 수동으로 수정하는 것이 효율적입니다.
DefinitelyTyped 참조: 널리 사용되는 자바스크립트 라이브러리들은 DefinitelyTyped 프로젝트에서 타입 정의를 제공하며, 이는 @types/ 접두사가 붙은 npm 패키지로 배포됩니다 (예: npm install @types/lodash).
새롭게 .d.ts 파일을 작성하기 전에, 사용할 라이브러리 타입 정의가 이미 존재하는지 먼저 확인하는 것이 좋습니다.
.d.ts 파일의 위치와 컴파일러 설정
.d.ts 파일은 특별히 임포트할 필요 없이 타입스크립트 컴파일러가 자동으로 프로젝트 내에서 찾아 인식합니다.
-
tsconfig.json의include:tsconfig.json파일의include배열에.d.ts파일이 포함된 디렉토리를 지정합니다. -
패키지 내
types필드: npm 패키지의package.json파일에types또는typings필드를 사용하여 주된 타입 정의 파일의 경로를 명시할 수 있습니다.package.json { "name": "my-cool-lib", "version": "1.0.0", "main": "dist/index.js", "types": "dist/index.d.ts" }types필드는 타입스크립트가 패키지의 대표 타입 정의 파일을 찾을 경로입니다. -
typeRoots및types:tsconfig.json의typeRoots옵션은 타입 정의 파일을 검색할 루트 디렉토리를 지정하며,types옵션은 전역적으로 포함할@types패키지를 명시합니다.
.d.ts 파일은 자바스크립트 생태계와의 상호 운용성을 확보하고 타입스크립트의 타입 안전성이라는 핵심 가치를 유지하는 데 필수적인 요소입니다.
자바스크립트 라이브러리를 사용할 때, 레거시 코드를 통합할 때, 또는 직접 타입스크립트 라이브러리를 개발할 때 .d.ts 파일을 올바르게 작성하고 활용하는 방법을 숙지하는 것이 중요합니다.
작성할 선언 파일의 형태를 고르기 전에는 “값은 이미 존재하고, 우리는 타입만 설명한다”는 기준을 먼저 세워야 합니다.
다음 표는 전역 선언, 모듈 선언, 배포용 선언을 고를 때 함께 볼 항목을 정리합니다.
.d.ts는 구현을 만들지 않고 이미 존재하는 JavaScript 값의 타입 표면만 설명합니다. 먼저 값이 전역인지, 모듈인지, 파일 에셋인지, 배포 산출물인지 구분합니다.
- 전역 값
global declare var , declare function , interface Window 로 script 태그가 만든 값을 설명합니다.
- 패키지 모듈
module declare module 'pkg' 안에서 named export와 default export를 실제 API에 맞춥니다.
- 파일 확장자
asset 번들러 파일 import 결과 타입을 정합니다.
- 배포 선언
package types 필드가 소비자 프로젝트에서 읽을 대표 .d.ts 위치를 가리킵니다.
- 구현을 쓰지 않습니다
no runtime 함수 본문이나 초기화 코드는 선언 파일에 두지 않고 시그니처와 구조만 남깁니다.
- 공개 표면만 적습니다
exact shape 내부 구현 세부사항보다 실제 사용자가 import하거나 전역에서 접근하는 이름을 우선합니다.
- 컴파일러가 읽어야 합니다
included include , typeRoots , 패키지 메타데이터 안에 선언 파일이 들어오는지 확인합니다.
선언 파일을 추가할 때는 타입이 맞는지만 보는 것이 아니라 값의 출처, 스코프, 배포 경로가 서로 맞물리는지도 확인해야 합니다.
선언 파일을 쓰기 전에는 런타임 값의 출처, 노출 스코프, 컴파일러 포함 경로가 맞는지 먼저 정리합니다.
- value값의 출처
value 전역 객체인지, npm 모듈인지, 로컬 JS 파일인지에 따라 선언 형태가 달라집니다.
- 범위선언 스코프
범위 최상위 export 가 있으면 모듈 선언, 없으면 전역 선언으로 읽힐 수 있습니다.
- include포함 경로
include include , typeRoots , 패키지 types 가 선언 파일을 실제로 보게 해야 합니다.
다음 절에서는 .d.ts 파일에서 사용되는 declare 키워드의 본질인 앰비언트 선언(Ambient Declarations)에 대해 더 자세히 알아보겠습니다.
다음 다이어그램은 .d.ts 파일 작성법을 선언 대상과 포함 범위 기준으로 정리한 표입니다.
declare, 전역 선언, 모듈 선언, tsconfig 포함 범위를 이해하면 자바스크립트 코드에도 TypeScript 사용 경험을 붙일 수 있습니다.
- 구현 없는 설명
declare 실제로 존재하는 변수, 함수, 클래스의 타입만 알려 주고 코드는 만들지 않습니다. declare function
- 어디서나 접근
전역 선언 브라우저 전역값이나 테스트 헬퍼처럼 import 없이 쓰는 이름을 설명합니다. declare global
- 패키지 표면
모듈 선언 특정 모듈에서 import 가능한 API의 타입을 선언합니다. declare module
- 컴파일러 인식
포함 설정 typeRoots, types, include 범위가 선언 파일을 실제로 읽는지 확인합니다. typeRoots
자바스크립트 라이브러리나 전역 값처럼 구현은 따로 있지만 타입 정보가 없는 대상을 TypeScript가 이해하도록 선언합니다.
- 타입 정보 점검
필요성 레거시 자바스크립트나 외부 라이브러리를 안전하게 쓰기 위해 공개 API의 타입을 적습니다. .d.ts
- 구현 없는 선언
declare 실제 값은 어딘가에 존재한다고 가정하고 타입 형태만 컴파일러에 전달합니다. declare
- 공개 API 중심
공개 API 선언 구조 내부 구현이 아니라 외부 사용자가 호출하는 함수, 객체, 모듈 형태를 기준으로 작성합니다. declare function
- 컴파일러 포함
위치 tsconfig include, typeRoots, 패키지 구조에 맞춰 선언 파일이 프로젝트에 잡히게 해야 합니다. typeRoots
아래 다이어그램은 .d.ts 파일이 JavaScript 코드와 TypeScript 타입 세계를 연결하는 방식을 정리합니다.
선언 파일은 구현 코드를 담지 않고 이미 존재하는 JavaScript 값과 모듈의 타입 모양을 TypeScript에 전달합니다.
- declare이미 존재함을 알림
declare 런타임에 값이 있다고 가정하고 그 값의 타입만 컴파일러에 설명합니다. declare const $
- 모듈 선언패키지 타입 설명
모듈 선언 타입이 없는 라이브러리나 자산 import에 대한 모듈 형태를 선언합니다. declare module "*.css"
- 전역 선언글로벌 API 점검
전역 선언 브라우저 전역 변수나 외부 스크립트가 제공하는 값을 타입으로 설명합니다. declare global
- 검색 위치tsconfig와 package types
검색 위치 include, typeRoots, package.json types 필드가 선언 파일 발견에 영향을 줍니다. types: "index.d.ts"