(create-react-app)Typescript 에서 window Object 확장하기(global.d.ts 적용 or react-app-env.d.ts 활용)
안녕하세요. 갓대희 입니다. 이번 포스팅은 [ Typescript 에서 window Object 확장해보기 ] 입니다. : )
[ 현재 환경 부가 설명 ]
현재 진행중인 프로젝트의 환경이 Typescript를 사용하며 CRA(create-react-app)로 만들어져 있다.
나의 경우, 현재 프로젝트의 많은 곳에서 window object 를 확장해서 사용하고 있었다.
기존에는 어떤 방법을 사용하고 있었고, 어떻게 변경 하여 사용하였는지 남겨 두려고 한다.
0. 문제점
- 그냥 window함수를 다음과 같은 예시로 확장하여 사용 하려 했다고 하자.
window.tempProperty;
// 또는
window.tmepProperty();
- 다음과 같은 오류가 발생할 것 이다.
<TS2339: Property 'tempProperty' does not exist on type 'Window & typeof globalThis'.>
- 이를 어떻게 해소할 수 있는지 알아 보도록 하자.
1. (window as any).property
- 현재 가장 간단하게 window Object를 any 타입으로 만들고 property에 접근할 수 있도록 해당 방법을 사용하고 있다.
ex) 위의 함수 예시도 다음과 같이 변경하면 오류 메세지가 사라지는것을 볼 수 있다.
(window as any).tempProperty
- 다만 any를 사용하여 타입체킹을 할 수 없으니 좋은 방법은 아닌 것 같다.
ex) Typescript Tips >>> https://typescript.tips/avoiding-window-as-any/
TypeScript Tips 에서 말하는 "avoiding window as any"
- 상기 내용을 살펴보면 말 그대로 (window as any)를 피하자, 사용하지 말자라고 하며 대안을 제시해 주고 있다.
1) 지양 해야할 내용
// 하기 내용은 지양 하도록 한다.
const myGlobal = (window as any).__MY_GLOBAL__
// ^? const myGlobal: any
2) 대안으로 제시하는 방법
- 하기와 같이 d.ts 파일에 확장하려는 속성(함수 또는 변수)을 declare(선언) 하여 사용 하도록 제안하고 있고, 해당 방법을 사용해보도록 하자.
//.d.ts를 정의 하여 사용하는 방법 제안
// global.d.ts
declare global {
interface Window {
__MY_GLOBAL__: number
}
}
export {} // Needed to augment global scope
// main.ts
const myGlobal = window.__MY_GLOBAL__
// ^? const myGlobal: number ✅
2. global.d.ts
- CRA에선 조금더 편하게 다른 방법을 사용할 수 있긴 하지만, 현재 Typescript 진영에선 global.d.ts를 권고 하는것을 확인 하였으니 해당 방법을 바로 사용하는 방법을 알아 보자.
- cra(create-react-app)환경에서는 global.d.ts 파일만 생성하면 안된다는 내용이 많아, 하기 2.1의 내용을 추가 하였다.
2.1 tsconfig.json 수정
- create-react-app으로 React+TypeScript 환경을 구성하였기에 "tsconfig.json" 파일이 있을 것이다.
- 해당 파일에 global.d.ts(타입을 선언할 용도)의 경로를 지정 해 준다.
ex) tsconfig.json
- 나의 경우 기존 프로젝트 구성을 고려하여 src밑의 types 폴더를 생성하여 선언해 주었다.
{
"compilerOptions": {
...
"typeRoots": ["src/types", "node_modules/@types"],
},
"include": ["src"]
}
2.2 globald.ts 생성 및 내용 입력
- 나의 경우 위에서 지정한 typeRoots 경로에 맞춰 파일을 생성하여 하기 예시와 같이 선언해 주었다.
// global.d.ts
export {}; // Needed to augment global scope
declare global {
interface Window {
tempProperty: Function; // Type 정의
}
}
- 내가 선언했던 tempProperty라는 함수의 다음 부분을 (window as any)에서 window로 변경 하였다.
- 상기 맨 처음 window.tempProperty 선언시에는 오류가 발생하였을 것 이다.
- 이제는 typechecker에서 오류를 뱉어 내지 않는다.
- 이로써 다 끝났다고 볼 수 있지만, CRA에서의 또다른 방법 한가지 더 추가로 알아보자.
3. react-app-env.d.ts
- CRA에서 "react-app-env.d.ts" 파일이 자동으로 생성 되었을 것이고, "process.env.환경변수이름" 을 활용하기위해 다음의 내용까지도 설정이 되어 있을 것 이다.
/// <reference types="react-scripts" />
- 이 파일을 활용하면 되고, interface Window {} 내용만 추가하면 된다.
( global scope 선언에 대한 부분은 해당 파일에선 필요 없다. 즉 declare global {...} block 부분은 생략. )
/// <reference types="react-scripts" />
interface Window {
tempProperty: Function;
}
※ 참고 : https://medium.com/@louisgv/typescript-and-create-react-app-env-e97def6b84e8
※ "react-app-env.d.ts"를 활용할지 "global.d.ts"를 설정하여 사용할지 고민이 많았다.
나의 경우 전역 변수나, 전역 함수를 위해 해당 내용을 진행 하다보니 이름부터 "global"이기도 하여 "global.d.ts"를 사용하는 방향으로 진행 하였는데, 명확하게 이게 맞다, 저게 맞다라고 하는 레퍼런스는 아직 확인하지 못했다.
※ 혹시라도 관련 내용을 좀더 자세히 내용을 알고 계신분이 계시다면, 댓글 남겨주시면 정말 감사합니다. 이후 내용 추가 내용 갱신 할 수 있도록 하겠습니다.