React + TypeScript | JavaScript에서 TypeScript로 변환 시 에러 모음

Positive Ko·2020년 12월 21일
11

TypeScript

목록 보기
4/6
post-thumbnail

오늘...
기존 JavaScript로 작성했던 프로젝트(초기 단계)를 TypeScript로 리팩토링하는 데에 성공했다.
오늘내로 컴파일이 될까 싶을 정도로 에러 화수분이었던 상황...
오전 10시부터 시작한 에러 대환장파티를 오후 4시에 마무리 짓는 데에 성공한다.
그 과정에서 기억하고 싶은 에러를 담아본다.
(TypeScript를 배운 지 3일차 타둥이의 글입니다.. 저와 같은 타입스크립트 스타터들을 위한 포스트임을 감안해주시길 바랍니다..🥺)


시작하기 전에

JavaScript로 작성하던 React 프로젝트를 TypeScript로 리팩토링하기 위해서는,

  1. 초기 CRA 명령어인 $ npx create-react-app ts-react-tutorial --typescript이 아니라,
    npm install --save typescript @types/node @types/react @types/react-dom @types/jest 혹은 yarn add typescript @types/node @types/react @types/react-dom @types/jest 이 명령어를 사용해야 합니다. (yarn add -g typescript도 필요합니다)

  2. js와 jsx 파일을 모조리 ts, tsx로 바꾸어 주세요.

  3. tsconfig.json 파일을 작성해야 합니다. (참고: tsconfig.json 사용하기)

  4. 기존에 사용하던 JavaScript용 라이브러리는 TypeScript용을 찾아서 다시 설치해야 합니다.
    "@types/lodash": "^4.14.149", "@types/react-slick": "^0.23.4", "@types/redux-logger": "^3.0.8" 등등...

  5. 자 이제 터미널에 뜨는 컴파일 오류를 하나씩 없애나가면 됩니다.

+@ IDE로 VSCode를 사용하시는 경우, 이 과정에서 VSCode가 정신을 못차립니다. 서버를 다시 껐다가 재시동하는 방법, node_modules를 삭제해서 다시 yarn install 해주시거나, VSCode 창을 완전히 껐다가 다시 켜는 방법.. 등 온갖 수단과 방법을 가리지 말고 시도해보세요 😇



1. Property '**' does not exist on type 'Window & typeof globalThis'. TS2339

Property 'kakao' does not exist on type 'Window & typeof globalThis'. TS2339

declare global {
  interface Window {
    kakao: any;
  }
}
const { kakao } = window;

외부 API인 kakao를 사용할 때, window 객체에 대한 정의가 필요했던 상황.
window의 interface를 선언함으로써 간단히 해결



2. Parameter 'event' implicitly has an 'any' type.ts(7006)

div에 onClick 이벤트를 걸어놓은 상황에서 event의 타입을 정의해야 했던 상황.
event: any로 처리해도 컴파일이 가능했지만 확실한 해결책을 찾고 싶었다.
결과적으로 다음과 같은 interface를 export해서 해당 컴포넌트에 import 한 후 사용하는 방법을 택했다.

export interface BaseSyntheticEvent<E = object, C = any, T = any> {
  nativeEvent: E;
  currentTarget: C;
  target: T;
  bubbles: boolean;
  cancelable: boolean;
  defaultPrevented: boolean;
  eventPhase: number;
  isTrusted: boolean;
  preventDefault(): void;
  isDefaultPrevented(): boolean;
  stopPropagation(): void;
  isPropagationStopped(): boolean;
  persist(): void;
  timeStamp: number;
  type: string;
}
  const tabHandler = (event: BaseSyntheticEvent): void => {
    if (!isWideTab) {
      setWideTab(!isWideTab);
    }
    const newTabState = { ...tabState };
    const activeTab = event.currentTarget.id;
    for (let key in newTabState) {
      key === activeTab
      ? (newTabState[key as keyof typeof newTabState] = true)
      : (newTabState[key as keyof typeof newTabState] = false);
    }
    setTabState(newTabState);
  };

참고사이트



3. TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type

Type '{ tabHome: boolean; tabBookmark: boolean; tabEtc: boolean; }' cannot be used as an index type. TS2538
객체를 갖고 노는 for ..in 문 작성 시 나타났던 에러다.

    for (let key in newTabState) {
      key === activeTab
      ? (newTabState[key as keyof typeof newTabState] = true)
      : (newTabState[key as keyof typeof newTabState] = false);
    }

2번 에러와 같은 코드 블럭 내의 에러였고 key를 객체(newTabState)의 keyof typeof로 정의하여 키의 값을 받아와 해결.
참고 자료



4. TS2533: Object is possibly 'null' or 'undefined'

  const handleSlide = (pixel: any) => {
    selectorRef?.current?.scrollTo({
      left: selectorRef?.current?.scrollLeft + pixel,
      behavior: 'smooth',
    });
  };

null과 undefined 처리를 해주어야 하는 상황. 옵셔널 체이닝으로 디버깅 완료.
참고 자료1
참고 자료2


5. Property '**' does not exist on type 'never'. TS2339

TypeScript로 useState작성 시에 const selectorRef = useRef(null);라고만 작성해도 무방하다. 굳이 const selectorRef = useRef<타입>(null); 타입을 작성하지 않아도 되는 이유는 알아서 타입을 유추하기 때문이다.
다만 ref가 null일 수도 있는 상황에서는 반드시 Generics를 사용해서 표기해주어야 한다.

  const selectorRef = useRef<HTMLDivElement>(null);

타입스크립트로 리액트 Hooks 사용하기 (useState, useReducer, useRef)



6. Cannot use JSX unless the '--jsx' flag is provided

node_modules를 지워봐도... VSCode를 껐다가 켜는 원시적인 방법을 사용했지만 해결되지 않았던 에러다.
먼저 command + shift + p를 누르고 TypeScript라고 치면 다음과 같은 창이 뜬다. Select a TypeScript Version..을 클릭.
TypeScript version을 4.1.2로 바꾸어 주면 해결!


참고 자료



이상 ... 자바스크립트로 쓰인 리액트 프로젝트를 타입스크립트로 변환하는 좌충우돌 우왕좌왕 후기였다.
솔직히 나중에 진이 빠져서 any를 남발한 경향이 조금 있긴 하지만😇, 앞으로의 리팩토링을 거쳐서 빈틈 없는 타입 정의로 디버깅이 필요없는 튼튼한 프로젝트를 만들고싶다!💪

그렇다면 앞으로도 let's fall in love with coding...💋





profile
내 이름 고은정, 은을 180deg 돌려 고긍정 🤭

4개의 댓글

comment-user-thumbnail
2020년 12월 21일

퀸은정과 함께여서 그나마 4시반에 끝난것 같습니다.... 정말 고생많으셨어여.... 그와중에 TIL까지.... 지존 짱... 머싯써...

1개의 답글
comment-user-thumbnail
2020년 12월 21일

대표님 안녕하세요
은은 잘 돌아가고 계신가요??
잘 지내시는것 같아 보기가 좋네요
너무 무리하지 말고 건강 챙기면서 쉬엄쉬엄 하세요
제가 좀 따라잡을 수 있게

1개의 답글