[TS] 개발자처럼 사용하기 1 : declare

Zero·2023년 10월 14일
5
post-thumbnail

살펴보게된 계기

타입스크립트로 프로젝트를 작업을 하면서 d.ts 문서들을 많이 들여다보면서 작업을 하였습니다. 해당 문서에서 자주 보이는 declare 의 사용 방법과 사용하는 이유를 올바르게 알고 실제 개발에서 사용을 하면 좋을 것 같아 찾아보았습니다.

declare가 뭐지? 왜 사용하는 걸까🙄?

declare는 직역을 하면 "선언을 하다"라는 뜻을 가지고 있습니다. 그럼 이 선언을 언제? 또 왜? 해야하는 것인지 예제를 통해서 알아보겠습니다.

Google Maps 플랫폼의 JS-SDK를 가져올 때 스크립트 태그로 다른 JS-SDK를 가져올 수 있습니다.

<script src="https://maps.googleapis.com/maps/api/js?key=Appkey..." defer/>

해당 코드를 불러온 이후에 SDK를 통해 불러온 API를 호출해줍니다.
정의되지 않은 google

Google Maps 개발 문서에 따라 SDK에서 제공하는 API를 호출하였지만 TypeScript 컴파일러는 위 코드에 해당하는 오류 메시지를 표시합니다. 이는 TypeScript 컴파일러가 전역 변수를 인식하지 못하기 때문입니다.

그렇다면 이를 해결할 수 있는 방법은 없을까요?

대답은 declare 키워드를 사용하여 google을 전역변수로 설정하는 것입니다.
정의된 google

declare를 통해서 선언을 한 전역변수에 대해서는 찾을수 없다는 에러가 발생하지 않습니다.

이는 declare를 통해 컴파일러에게 나는 이미 정의되어 있는 타입이야. 나는 바로 사용할 수 있어 와 같이 친절하게 미리 알려주는 것입니다.

이를 위해서 좀 더 타입스크립트 코드를 뜯어보겠습니다.

// typescript/lib/lib.es5.d.ts
declare var NaN: number;
declare var Infinity: number;
declare var JSON: JSON;

저희가 이전에 사용하고 있던 NaN , Infinity , JSON 도 이미 선언이 되어있었습니다. 이처럼 실제 전역 변수 선언 이외에도 선언 키워드를 사용하여 전역 함수, 전역 클래스등을 선언할 수도 있습니다.

// typescript/lib/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를 통해 선언을 해서 사용하면 되겠구나!

이 말은 맞는 말이기도하지만 더 좋은 방법이 있습니다. 이미 만들어져있는 Typed 프로젝트의 d.ts 파일을 찾는다던지 혹은 해당 라이브러리의 d.ts 파일을 받아오는 것입니다.

d.tsdeclare typescript의 약자로 타입 선언 파일 뒤에 붙이는 확장자명입니다.

해당 Google Maps의 경우 해당 라이브러리의 문서를 읽을 경우 사용 가이드를 찾을 수 잇습니다. 그런 다음 npm을 사용하여 설치할 수 있습니다.

npm i -D @types/ggole .maps

-D 로 설치하는 이유는 클라이언트에서는 해당 타입검사가 필요가 없기 때문입니다.

declare의 다양한 용도들

declare의 다른 용도들에 대해서도 알아보겠습니다. Vite 프로젝트를 사용한다면 해당 폴더를 열면 다음과 같이 clident.d.ts 모듈을 선언하는 코드들이 많이 보입니다.
vite

왜 모듈을 선언해야 할까요? 모듈을 선언하지 않으면 안되나요? 선언하지 않으면 TypeScript 컴파일러가 이러한 모듈을 인식하지 못하고 해당 오류 메시지가 표시되기 때문입니다.

error
모듈을 선언할 때는 각 리소스를 해당 모듈과 함께 선언하는 것을 피하기 위해 TypeScript 2.0에서부터 와일드카드(*) 형식을 지원하기 시작하였습니다.
wild

또한 declare를 이용하여 기존 모듈에 정의된 유형을 확장할 수 있습니다.

import { AxiosInstance } from "axios";
declare module "@vue/runtime-core" {
  interface ComponentCustomProperties {
    $axios: AxiosInstance;
  }
}

그런 다음 globalProperties 구성 개체의 속성을 사용하여 $axios 각 구성 요소에 속성을 추가 및 사용할 수 있습니다.

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));

개발자처럼 사용해보기

  1. svg 파일을 컴포넌트로 만들어서 사용하기

    declare를 통해서 사용할 수 있는 가장 방법들은 위에있는 것들 말고도 여러가지 방법들이 있습니다 예를 들어서 다음과 같이 .svg 파일을 ReactComponent로 사용하는 방법도 있습니다.

  declare module '*.svg' {
    import React = require('react');
    export const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
    const src: string;
    export default src;
  }
  import { ReactComponent as DeleteIcon } from '@assets/svg/deleteIcon.svg';

  const DeleteIconComponent = () => {
    return <DeleteIcon/>
  }
  1. .env 파일 정의를 할 때 사용하기
    typeScript를 사용한다면 env 파일을 읽어올 수 없습니다.
    env

만약 vite를 사용한다면 ImportMeta 를 정의를 해줘야합니다. 만약 여기서 자동완성까지 가능하게 한다면 개발 생산성을 향상시킬 수 있습니다.


   VITE_NAVER_CLIENT_KEY: string;
   VITE_GOOGLE_CLIENT_ID: string;
 }
}

interface ImportMeta {  import 'vite/client';

declare global {
 interface ImportMetaEnv {
   VITE_BASE_URL: string;
   VITE_BACK_URL: string;
   VITE_KAKAO_KEY: string;
   VITE_KAKAO_REST_API: string;
   VITE_NAVER_CLIENT_ID: string;

 readonly env : ImportMetaEnv
}

위 코드에서는 ImportMetaEnv 를 정의해줌으로서 자동완성이 가능하게 변경을 해주었습니다.

자동완성

vite 를 사용하지 않고 CRA환경에서 개발한다면 다음과 같이 설정할 수 있습니다.

declare namespace NodeJS {
    export interface ProcessEnv {
        BASE_KEY: string;
        API_KEY: string;
    }
}

-------
  
const App = () => {
	return <div>{process.env.API_KEY}</div>
}

마무리

처음으로 하는 타입스크립트 프로젝트가 마무리단계에 오면서 프로젝트를 되돌아보면 declare 와 같이 개발 향상성에 도움이 되는 다양한 기능등이 있지만 타입스크립트를 온전히 활요하지 못한거 같았습니다. 앞으로는 declare 를 활용하는 개발자가 되기를..😂

profile
0에서 시작해, 나만의 길을 만들어가는 개발자.

0개의 댓글