TypeScript: 'Property does not exist on type Window' 전역 객체 확장 및 global.d.ts 선언 병합 해결법
- 원인: 타입스크립트가
window타입을 브라우저 표준 사양으로 고정해둬서, 외부 스크립트가 주입한window.kakao같은 커스텀 속성을 모르는 속성이라며 막음 - 해결: 자주 쓰는 SDK는
global.d.ts에 선언 병합 / 1회성이면(window as any)단언 / 메이저 도구는@types/패키지 설치 - 주의: 카카오맵·GTM처럼 <script> 태그로 직접 로드하는 외부 SDK를 쓸 때 특히 자주 마주치는 에러
declare global { interface Window { kakao: any; } }
export {};
↓ 왜 이런 에러가 나는지 원리 보기
카카오 로그인이나 GTM처럼 <script> 태그로 불러오는 외부 SDK를 쓰다 보면, 자바스크립트에서는 문제없던 코드가 TypeScript에서 'Property does not exist on type Window' 에러를 내는 경우가 있습니다. window 객체에 전역 스크립트가 주입한 커스텀 속성을 안전하게 다루는 방법 세 가지를 정리합니다.
왜 'does not exist on type window' 에러가 발생하는가
타입스크립트는 브라우저 웹 API 사양에 근거해 기본 window 객체의 타입을 고정해 두었습니다. 이 때문에 런타임에 외부 스크립트가 강제로 주입한 커스텀 객체(예: window.kakao 또는 window.daum)가 들어오더라도, 컴파일러는 "그런 객체는 공식 사양에 존재하지 않는다"며 즉각 컴파일 에러를 일으키는 것입니다. 자바스크립트의 동적 자유도와 타입스크립트의 정적 엄격성 사이에서 흔히 일어나는 충돌 양상입니다. 카카오맵이나 GTM처럼 <script> 태그로 직접 로드하는 외부 SDK를 쓸 때 특히 자주 마주치는 에러입니다.
기본 Window 타입은 브라우저 표준 DOM 사양에 고정되어 있어 window.kakao처럼 외부 SDK가 주입한 속성을 참조하면 존재하지 않는 속성이라며 에러를 냅니다. global.d.ts 같은 전역 확장 파일을 만들어 선언 병합(Declaration Merging)을 적용하면 이런 속성도 기본 Window 타입에 안전하게 합쳐져 에러 없이 사용할 수 있습니다.
Window 타입을 확장하는 3가지 우회 전술
방법 A: global.d.ts 파일로 전역 인터페이스 선언 추가 (가장 권장)
가장 정석적인 해결법입니다. 전역 타입 정의용 폴더/파일을 생성하여 타입스크립트의 선언 병합(Declaration Merging) 특징을 활용해 Window 규격서 자체를 확장합니다. global.d.ts 파일을 만드신 후 아래 코드를 기입하세요.
declare global {
interface Window {
// 1. 외부 카카오 SDK용 타입 추가 (임시 any 설정)
kakao: any;
// 2. 구글 애널리틱스 로그 수집 레이어용 타입 추가
dataLayer: any[];
}
}
// 이 파일이 전역 모듈임을 타입스크립트 컴파일러에 인지시키기 위해 빈 export 추가
export {};
방법 B: 타입 단언(Type Assertion - any 우회)
임시로 빠르게 작업을 마쳐야 하거나, 1회용 컴포넌트 내부에서만 짧게 쓰고 말아야 할 때 유용한 일회용 우회법입니다.
// window 객체를 강제로 any 타입으로 형변환하여 컴파일 가드를 우회합니다.
const kakaoSdk = (window as any).kakao;
if (kakaoSdk) {
kakaoSdk.maps.load(() => {
console.log("지도 로드 성공");
});
}
방법 C: 외부 타입 라이브러리(@types/... ) 공식 패키지 설치
만약 연동하려는 오픈소스 라이브러리가 전 세계적으로 많이 쓰이는 것이라면, 굳이 직접 타이핑을 작성할 필요 없이 개발자 커뮤니티가 기정의해 놓은 공식 패키지를 DevDependency로 깔아서 통과하는 것이 좋습니다.
# 예시: 구글 애널리틱스(gtag)용 전역 타입 패키지 설치
npm install --save-dev @types/gtag.js
카카오 로그인을 붙이는 작업에서 window.Kakao를 아무 데서나 (window as any)로 눌러쓰다가, 나중에 오타로 window.Kako라고 잘못 쓴 곳을 컴파일러가 전혀 못 잡아준 적이 있습니다. 그때부터는 처음 SDK를 붙이는 시점에 global.d.ts부터 만들어두는 쪽으로 습관을 바꿨습니다.
요약: 전역 Window 객체 확장 전략 매트릭스
글로벌 객체 오염을 방지하고 안전하게 타입을 병합하는 우회 전략 테이블입니다.
| 상황 | 원인 및 리스크 | 추천 해결 기술 |
|---|---|---|
| 반복적인 타사 SDK 연동 (카카오 등) | 여러 파일에서 window 속성 참조 시 중복 빌드 에러 노출 | global.d.ts 선언 병합 확장 |
| 임시 기능 개발 및 1회성 스크립트 | global.d.ts 파일 세팅을 위한 불필요한 공수 최소화 시 | (window as any) 임시 단언 |
| 구글 태그, 유튜브 API 등 메이저 도구 | 검증되지 않은 임의의 type 사용으로 타입 안정성 저하 우려 | @types/ 전용 패키지 추가 |
타입스크립트의 선언 병합 아키텍처에 대한 공식 문서는 아래에서 확인할 수 있습니다.
실무에서는 자주 쓰는 SDK라면 global.d.ts로 타입을 한 번 정의해두고, 1회성 스크립트라면 (window as any)로 짧게 우회하는 식으로 상황에 따라 나눠 쓰는 편이 낫습니다.
댓글
댓글 쓰기