declare를 명확하게 알고있지 않아서 검색하다가 이 글 을 번역하였다.
(이 글에서의 declare사용은 구글맵을 예시로 하고 있지만, 카카오맵을 타입스크립트+리액트에서 사용할 때에도 적용할 수 있다.)
원문 : https://javascript.plainenglish.io/purpose-of-declare-keyword-in-typescript-8431d9db2b10
Purpose of Declare Keyword in TypeScript
A Detailed Introduction to the Role of TypeScript Declare, so You Are Not a Stranger to *.d.ts Files.
javascript.plainenglish.io
아래의 글은 위 원문을 번역한 글(의역)입니다.
타입스크립트에서 declare의 목적
만약 당신이 타입스크립트 프로젝트에서 *.d.ts
를 열어본다면 declare
를 본적이 있을 겁니다.declare
가 어떤것인지 잘 아시나요? 만약 모르신다면 이 글을 읽고나서는 알게 될 것입니다.
타입스크립트 프로젝트에서, 당신은 써드파티 JS-SDK를 script tag 형식으로 import 하게 될 수도 있습니다. 가령 구글맵처럼 말입니다.
<script
src="https://maps.googleapis.com/maps/api/js
?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly" defer></script>
위와 같이 선언한 후에는, 당신은 해당 API를 호출할 수 있습니다.
이때 당신이 구글맵 공식문서를 보고 JS-SDK로 제공되는 API를 사용했을지라도,
타입스크립트 컴파일러는 에러를 띄울것입니다.
타입스크립트 컴파일러는 google
이라는 전역 변수를 인식하지 못하기 때문이죠.
그럼 이 문제를 어떻게 해결할 수 있을까요??
declare
를 사용하여 google
이라는 전역변수를 선언하는 것입니다.
declare var google: any;
이를 통해 타입스크립트 컴파일러는 전역변수를 인식할 수 있습니다.
혹시 이러한 방식을 보고, 혼란스러우신가요??
왜 당신은 JSON, Math, Object 같은 전역변수들을 타입스크립트 프로젝트에서 사용할 수 있을까요??
타입스크립트는 우리(개발자)를 위해 내부적으로 '선언' 이라는 행위를 하고, 일찍이 언급되었던 전역변수들은 lib.es5.d.ts
라는 declaration file에 선언되기 때문입니다.
// typescript/lib/lib.es5.d.ts
declare var JSON: JSON;
declare var Math: Math;
declare var Object: ObjectConstructor;
추가로 전역 변수 뿐만 아니라, 전역 함수, 전역 클래스, 전역 enum 등을 선언할때도 declare
를 사용할 수 있습니다.eval
,isNaN
,encodeURI
,parseInt
등의 함수들도 lib.es5.d.ts
에 이미 선언되어 있습니다.
declare function eval(x: string): any;
declare function isNaN(number: number): boolean;
declare function encodeURI(uri: string): string;
declare function parseInt(string: string, radix?: number): number;
이 때 알고 계셔야 하는 것은, 우리가 declare
를 통해 전역함수를 선언할 때, 함수의 기능은 다루지 않는다는 것입니다.
다만 우리는 타입스크립트 컴파일러가 위 전역 JS 함수를 인식할 수 있게 합니다.
사실 앞서 보여준 google
을 찾지 못하는 이슈에 대한 이러한 솔루션은 상대적으로 폭력적??(relatively violent)입니다.
더 좋은 솔루션은 타입스크립트 웹사이트 나 DefinitelyTyped project(다양한 타입 선언들을 참고할 수 있는 오픈소스) 에서 제공하는 type declaration file serach function을 사용하는 것입니다. 그리고 당신은 더욱 수준높은 서드파티 라이브러리를 통해 타입스크립트 타입 선언을 할 수 있습니다.
위의 정보들을 알게 되었다면, 당신은 npm을 이용하여 모듈을 설치하고 필요한 타입선언을 할 수 있습니다. 만약 당신이 Google Maps와 타입스크립트 사용자를 위한 가이드를 읽었다면, 당신은 type declaration file을 찾았을 것이고, npm 으로 설치할 수 있었을 것 입니다.
npm i -D @types/google.maps
npm package 'foo'의 경우에는 '@types/foo'를 이용할 수 있습니다. 예시로 jquery library와 대응하는 @types/jquery
가 있습니다.
이제 declare의 또 다른 용례를 살펴봅시다. 우린 client.d.ts
안에서 모듈들을 선언하는 수많은 코드들을 볼 수 있습니다.
위 코드에서 우린 css
,jpg
,ttf
모듈들이 선언된 것을 볼 수 있습니다. 왜 우린 이러한 모듈들이 필요할까요??
만약 위의 모듈들을 선언하지 않았다면 타입스크립트 컴파일러는 위 모듈들을 인식하지 못하고 에러를 뱉기 때문입니다.
또한 각각의 모듈이 하나하나 선언해주는 것(귀찮은작업)을 피하고자, 타입스크립트2.0에서는 wildcard(*)
형식을 지원합니다.
추가로, 타입스크립트는 declare
를 통해 기존에 선언된 타입을 확장하는 것도 가능하게 해줍니다.
예를들면 만약 당신이 axios
에 Vue component instance
를 붙히고(add) 싶다면 다음과 같이 작성할 수 있습니다.
import { AxiosInstance } from "axios";
declare module "@vue/runtime-core" {
interface ComponentCustomProperties {
$axios: AxiosInstance;
}
}
그리고 config 객체의 globalProperties
프로퍼티를 사용하여 효과적으로 axios
프로퍼티에 각 컴포넌트 인스턴스를 붙힐 수(add) 있습니다.
import { createApp } from "vue";
import axios from "axios";
import App from "./App.vue";
const app = createApp(App);
app.config.globalProperties.$axios = axios;
app.mount("#app");
마지막으로, 컴포넌트에서 당신은 컴포넌트 내부 인스턴스의 proxy.$axios
프로퍼티를 통해 axios 객체에 접근할 수 있습니다.
import { getCurrentInstance , ComponentInternalInstance} from "vue"
const { proxy } = getCurrentInstance() as ComponentInternalInstance
proxy!.$axios
.get("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => response.data)
.then((json) => console.log(json));
이 글을 읽고, 난 이미 당신이 declare
와 몇가지 실용적인 시나리오를 이해했을 것이라 믿습니다.
만약 타입스크립트에 대한 전문성을 더 키우고 싶다면 Matering TypeScript 시리즈를 놓치지 마세요.
'개발 > TypeScript' 카테고리의 다른 글
런타임때에 사라지는 타입 (0) | 2023.01.18 |
---|---|
타입스크립트는 타입 오류가 있어도 컴파일을 한다. (0) | 2023.01.18 |
Generic (0) | 2022.05.09 |
Enum (0) | 2022.05.06 |
Never 타입 -> 내 코드가 뭔가 문제가 있구나! (0) | 2022.02.10 |