본문 바로가기

Today I Learned (TIL)

리액트에서 타입스크립트 사용시 기초개념 23.12.14

728x90
반응형

 

리액트에서 타입스크립트를 바로 적용할수있도록 기본 개념들을 배워보았다


 

1. 함수에서 TS 사용하기

 

function sum(a: number, b: number): number {
  return a + b;
}
// 이렇게 인자 부분에 일일히 : 으로 오른쪽에 원하는 타입을 넣어 줄수도있지만 

function objSum({ a, b }: { a: number; b: number }): string {  //리턴하는 부분도 string 형식이기에
 오브젝트(객체) 형식으로 이용 할시에는 넘어가는 객체에 { a: number; b: number } 이런식으로 지정가능
  return `${a + b}`; 
} // 백틱 `` 을이용하여 문자열로 바꿔 주어야 오류없이 함수에서 TS가 사용가능하다 
 

2.비동기 함수에서 TS 사용하기

Ts.node 를이용해 정보를 불러왔다 아이디 나이 신장 이 적혀있는 배열[] 안에 객체{} 가있는 모습이다

type Person = { id: number; age: number; height: number };
// 일단은 각 객체안에 정보에 type을 설정해준다 

async function getPerson(): Promise<Person[]> {
// 비동기 함수는 Promise 를 반환해야하기에 Person 타입을 제네릭<> 로 감싸준다
  const res = await fetch(`http://localhost:5008/people`);
  if (!res.ok) {
    throw new Error();
  }
  return res.json();  //   return res.json() as any as Person[]  이런 방식으로 사용가능하지만 비추
}

getPerson().then((res) => console.log(res[0]));  //이제 res[0].id   .age  .height 등등 사용가능
 

 

 

4. TS 꿀팁! Create React App, ts-pretty-error extension

 

4-1 해당 명령어 사용시 간편하게 타입스크립트 리액트 기초 세팅 가능하다

npx create-react-app 아무-이름-가능-합니다 --template typescript
 
설치전
 

지금 a의 타입을 number로 지정해 놓고 "" string 을 사용하니 오류가 나오는데

설치후

 

Pretty TypeScript Errors 를 설치해주면 말그대로 이쁘게 오류를

알려준다 Ts 사용시 오류 잡기 더욱더 쉬워지는 확장익스텐션이다

 

5. Generic <T>에 대한 아주 간단한 이해

(타일을 일반화 한다 == 타입을 변수화 한다)

// 제네릭(generic)이란 데이터의 타입(data type)을 일반화한다(generalize)는 것을 의미합니다.
type Generic<T> = {  // T 대신 무거나 ex) abc, dqwwqff, qwer 등등 들어가도되지만 보통 T 를쓴다 
  someValue: T;
};

type Test = Generic<string>;

function someFunc<T>(value: T) {} // 함수옆에 <T> 를 넣어주면 그대로 value에도 들어간다 

someFunc<string>("hello");
 

Generic 에 넣어준 <string> 이 Test 에도 들어간걸 확인할수있다

함수도 <> 미리 타입을 넣어주면 value에도 자동으로 들어간다

 

6. useState 에서 사용하기

import { useState } from "react";

function App() {
  const [counter, setCounter] = useState<number>(1); //타입을 number 로 지정시에는 () 숫자만 넣어줘야
  const increment = () => {                               //오류가 발생하지않는다 
    setCounter((prev) => prev++); //useState 에서 이미 number로 지정을 해줬기에 
  };                               //prev 는 자동으로 number로 지정되어있다. 다른걸로 변경시오류
  return <div onClick={increment}>{counter}</div>;
}

export default App;
 

그냥 useState 옆에 <> 제네릭을 사용하면된다.

const [counter, setCounter] = useState<number>(1)

여기에 () 빈칸으로 둘경우에는 {counter} 에는 number | undefined 라고 표시된다

제네릭 사용없이 useState(1) 사용할경우에는 자동으로인식해서 number 표시함.

 

7. Passing Props

 

보통 props 를 내려줄때는 return <Child count={count}></Child>; 후에

function Child({ count }) 이런식으로 받으면 되지만 TS 에서는 불가하다

import { useState } from "react";

function Parent() {
  const [count, setCount] = useState(""); /1/내려줄때 ""(string)을 초기값으로 넣어주면 자동인식해
  return <Child count={count}></Child>;                    
}

type Props = {          /3/ 근데 이렇게 쓰면 쓸게 너무 많아지니까 타입을 정해서 사용가능함
  count: string;
};

function Child({ count }: Props) {    /2/ Child({ count }:{ count:string}) 으로 받을수있다 
  return <div>{count}</div>;
}

export default Parent;
 

props 옆에 : <아무 타입(string,number,symbol 등등...> 넣어주면 porps 가능하다

근데 하나하나 쓰면 너무 많은관계로 이렇게 묶어서 사용도 가능하다

 

8. Children Props

 

이제는 리액트 18버전이 업데이트가 되어서 사용되지않는 Reat.FC 이지만

아직 사용하는 회사들도 있다고 해서 간단 정리 (23.12.14기준)

type BaseType = {  //이렇게 지정 한 베이스 타입을 넣어주기만 하면 사용가능 했다...
  id: string;         //FC 라는 타입안에 암묵적으로 칠드런이라는 타입을 가지고있었음 
};

//React 18버전 이전  //FC == Functional Components 줄임말
const Child: React.FC<BaseType> = ({ id }) => {
  return <div>{id}</div>;
};

export function Parent() {
  return (
    <Child id="">   // 암묵적으로 들어가있는 칠드런이라 가독성도 안좋고 소통오류도 생김
      <div>has children</div>
    </Child>
  );
}
 

18버전 이후 리액트에서 사용법

PropsWithChildren

import { PropsWithChildren } from "react";

type BaseType = {
  id: string;
};
 // 이름부터 직관적이다 
function Child({ children }: PropsWithChildren<BaseType>) {
  return <div>{children}</div>;
}

export function Parent() {
  return <Child id=""></Child>;
}
 

이름부터 직관적인 PropsWithChildren (칠드런을 사용해서 프랍스를만든다)

사용법은 React.FC 와 비슷하다 베이스 타입을 제네릭에 넣어주기만 하면 사용가능하다.

단점이라면 PropsWithChildren 도 옵셔널하게 choldren을 가지고있다

이말은 칠드런을 넘기지 않아도 오류가 생기지않는다는거고

몇몇 사람들은 이것도 명시적이지 않다고 한다

(엄격하지않음 칠드런 안넣은오류 못잡으니)

하지만 실제 사용하는데 큰 문제는 없다 (튜터 추천)

 

그래서 좀더 엄격한기준으로 프랍스를 TS에서 사용할수있는 방법

import { ReactNode } from "react";

type BaseType = {
  id: string;
};

type StrictChildren<T> = T & { children: ReactNode };
// 이름은 그냥 아무거나 (StrictChildren)지어도 상관없음 
//이부분 에서 중요한점은 타입을 만들어주는것 아무이름 <T> = T & { children: ReactNode };
// 제네릭으로 타입을 넣어주고 칠드런을 만들어서 사용하는 점 (타입 + 칠드런)

function Child({ children }: StrictChildren<BaseType>) {
  return <div>{children}</div>;
}

export function Parent() {
  return (
    <Child id="">
      <div>chlidren</div> // 이부분을 지워주면 바로 오류가 난다 
    </Child>
  );
}
 

이방식으로 사용할시에 칠드런을<div>chlidren</div> 넣어주지 않으면 바로

오류가 나는것도 확인이 가능하다

 

9. Generic, Utility Type 통해서 Props용 Type 만들기

import {
  AddressComponent,
  PersonChildComponent,
  ProfileComponent,
} from "./UtilityTypeChildren";

export type PersonProps = {
  id: string;
  description: string;
  address: string;
  age: number;
  profile: string;
};

export const PersonComponent = ({
  id,
  description,
  address,
  age,
  profile,
}: PersonProps) => {
  return (
    <>
      <PersonChildComponent>
        <div>{id}</div>
      </PersonChildComponent>
      <ProfileComponent
        description={description}
        address={address}
        age={age}
        profile={profile}
      />
      <AddressComponent address={address} />
    </>
  );
};
 

위에 코드를 받아서 아래코드에 적용중이다

import { PropsWithChildren, ReactNode } from "react";
import { PersonProps } from "./UtilityType";

export const PersonChildComponent = ({ children }: PropsWithChildren) => {
  return <>{children}</>;
}; // 제네릭 사용없이 칠드런만 받아올수있다 

type OmitType = Omit<PersonProps, "id">;
// 오밋을 사용하면 특정 타입만 빼고 다시 만들어 사용이 가능하다 (여기서는  id만뺐다)

export const ProfileComponent = ({
  description,
  address,
  age,
  profile,
}: OmitType) => {
  return <></>;
};

type PickType = Pick<PersonProps, "address">;
// Pick 은 Omit 과 문법은 똑같지만 원하는 타입만 가져올수있다 

export const AddressComponent = ({ address }: PickType) => {
  return <></>;
};
 

오밋으로 여러 타입을 제외할때에는 타입 이후 , 한번만 작성후

유니온 타입으로 | 표시를 이용해야 한다

 

10. Event Handler 사용하기

import { useState } from "react";

function App() {
  const [counter, setCounter] = useState<number>(1);

  const eventHandler = (e: React.MouseEvent<HTMLDivElement>) => {};

  return <div onClick={eventHandler}>{counter}</div>;
}

export default App;
 

const increment = (e) => {e.targrt.value}; 에서 e 에도 타입을 넣어주어야하는데

온클릭부분에 e를 넣어주고 마우스를 올려주면 어떤 타입을 사용했는지

추론해주는데 그대로 복사해 사용주어도된다

이렇게 아무문제 없이 사용가능하다

increment 를 직접 온클릭에 넣어주어도 괜찮다

좀더 간단한 방법은

온클릭에 호버(마우스를올리면) 마우스 이벤트 핸들러에는 마우스 이벤트가 온다는걸 알수가있다

같은 원리로 onChange에는 폼 이벤트 핸들러가 오는걸 알수있다

이를 이용해서 폼이벤트를 사용한다는걸 추측할수있다

 

아까처럼 복사 붙여넣기 길게 할필요없이 이런 이벤트를 제출하겠구나 추측후

필요한 폼이벤트만 불러와서 increment에 할당후 온체인지에 넣어주면

정상작동 한다는걸 알수가있다.

타입을 찾기 힘들때는 호버링만 하면 친절하게 리액트에서 알려준다


뭔가 어려운거같지만 익숙해지면 쉽다고하는데... ! 일단은 많이 반복하면서

실제 코드에 적용시켜보는 연습은 필수인거같다.

이렇게 TIL 에 정리하니 좀 더 이해가 빠른거같기도하고

728x90
반응형