TypeScript

제동현·2023년 2월 7일
0
post-thumbnail

TypeScript란

TypeScript는 JavaScript랑 기반이 비슷하나 거기에 기능이 살짝 추가된거라고 보면된다.

예를 들어

const plus(a,b) => a+b

가 있다고 치자 여기서

plus(2,2) 를 치면 4가 나올것이고

plus(2,hi)를 치면 2hi가 나온다.

근데 저렇게 표시가 안되고 a,b에는 숫자가 들어간다고 데이터타입에 대한 약속이 필요할때가 있다.

즉 코드에 실수가 있어도 프로그램이 작동하기전에 알려주는 역할을 TypeScript가 하는것이다.

const user = {
  firstName: "Angela",
  lastName: "Davis",
  role: "Professor",
}
 
console.log(user.name)
Property 'name' does not exist on type '{ firstName: string; lastName: string; role: string; }'.

예를 들어 이런 느낌이다.
콘솔로그에 name을 찍었는데 user는 name을 가지고 있지 않고 다음 타입을 가지고 있다고 알려주는거지

설치

npm install --save typescript @types/node @types/react @types/react-dom

를 입력해서 설치해주자 그게 아니라 처음부터 설치한다면

npx create-react-app 내 앱 이름 --template typescript
npm i --save-dev @types/styled-components
npm i styled-components

이렇게 전부 설치해주면된다.

TypeScript는 js대신 ts확장자와 react와 함께 사용할땐 tsx확장자명을 사용한다.

Typeing the Props

이말은 TypeScript에게 React component를 어떻게 설명하는가 이다.

전에 배운 Prop Types는 브라우저의 콘솔에 경고표시를 해주는 기능이 있었다.

하지만 TypeScript는 결과를 표시하기"전"에 오류를 표시해준다.

근데 props의 object shape를 설명해주지 않으면 TypeScript가 이해를 하지 못한다.

예시

import styled from "styled-components";

const Container = styled.div``;

interface CircleProps {
  bgColor: string;
}

function Circle({ bgColor }: CircleProps) {
  return <Container />;
}

export default Circle;

그래서 interface 인터페이스이름 {object 형태 }
로 정의한다.

import styled from "styled-components";

interface ContainerProps {
  bgColor: string;
}

const Container = styled.div<ContainerProps>`
  width: 200px;
  height: 200px;
  background-color: ${(props) => props.bgColor};
`;

interface CircleProps {
  bgColor: string;
}

function Circle({ bgColor }: CircleProps) {
  return <Container bgColor={bgColor} />;
}

export default Circle;

근데 여기서 {bgColor}:CircleProps를 넣었을때 에러가 난다.
return 부분에서 TypeScript가 Container를 div로 인식하기 때문에 일어나는 에러다.

그래서 위에 interface를 하나더 추가한뒤 ContainerProps라고 명명하고
bgColor를 string 으로 정의한뒤 Container styled componnet 정의를 한 부분에다가 <ContainerProps>를 추가해주니 오류가 없어지고 정상적으로 박스 2개가 출력된다.

근데 우리가 지금 interface CircleProps에 설정해준 bgColor: string은 필수옵션이다

<Circle />콤퍼넌트에 무조건 들어가야함 <Circle bgColor="tomato"/> 이런식으로 안그러면 오류가난다 벌겋게

한마디로 required라는 소리다 저걸 optional 로 바꾸는 방법은 무엇일까
예를 들어 bgColor말고 borderColor를 추가하고자한다.

interface CircleProps {
bgColor: string;
borderColor: string;
}

이렇게 그러면 다시 Circle 콤퍼넌트를 사용한곳에선 난리를 치겠지?

borderColor는 필수인데 왜 안넣었음?!

function App() {
return (
  <div>
    <Circle bgColor="teal" />
    <Circle bgColor="tomato" />
  </div>
);
}

export default App;

이때 borderColor끝에 ?를 붙여주면 끝난다

interface CircleProps {
  bgColor: string;
  borderColor?: string;
}

진짜 이게 끝임

하지만 문제가 하나 더 생기는데

interface ContainerProps {
  bgColor: string;
  borderColor: string;
}

interface CircleProps {
  bgColor: string;
  borderColor?: string;
}

CircleProps에서 borderColor를 옵션으로 지정했으나 ContainerProps에선 옵션으로 지정되어 있지 않아서 오류가 뜬다.

function Circle({ bgColor, borderColor }: CircleProps) {
  return <Container bgColor={bgColor} borderColor={borderColor ?? bgColor} />;
}

그래서 우리는 borderColor가 지정되지 않았을때 즉 undefine일때 기본값을 지정해 줘서 오류를 없앴다.

text도 적용할 수 있어

interface CircleProps {
  bgColor: string;
  borderColor?: string;
  text?:string;
}

function Circle({ bgColor, borderColor, text="default text" }: CircleProps) {
  return (<Container bgColor={bgColor} borderColor={borderColor ?? bgColor}>
    {text}
    </Container>
    );
}

text도 옵션으로 지정하고 Circle props에 text를 추가해
그리고 undefine의 경우엔 text="default text"로 지정해주면되

import Circle from "./Circle";

function App() {
  return (
    <div>
      <Circle borderColor="black" bgColor="teal" text="eh?"/>
      <Circle bgColor="tomato" />
    </div>
  );
}

export default App;

위 코드 처럼 text가 따로 지정되어 있지 않으면 default text라는 문구가 출력되는 형식이야.

State

TypeScript는 똑똑하기때문에 useState에 사용된 초기값을 가지고 추론하여 value와 수정해줄함수의 data type을 경고해준다.

만약에 const [counter, setCounter] = useState(1);라고 지정해줬다면 State타입은 변하지 않으므로 계속 number를 쓰게 될것이다.

근데.. 만약 number로 시작해서 string으로 끝나는 일이 있다고 한다면?

const [counter, setCounter] = useState<number|string>(0);

다음과 같이 코드를 작성해주면 된다 하지만 이는 자주 사용되진 않는다 알고는 있자!

Form

Reactjs TypeScrit를 이용해서 form에 타입을 적용하는 방법이다.

import React, { useState } from "react";

function App() {
  const [value, setValue] = useState("");
  const onChange = (event: React.FormEvent<HTMLInputElement>) => {
    const {
      currentTarget: { value },
    } = event;
    setValue(value);
  };
  const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    console.log("hello", value);
  };
  return (
    <div>
      <form onSubmit={onSubmit}>
        <input
          value={value}
          onChange={onChange}
          type="text"
          placeholder="username"
        />
        <button>Log in</button>
      </form>
    </div>
  );
}

export default App;

ES6 문법이다. event안 curentTarget안에 value의 값을 기존 이름 그대로 value 라는 변수를 만든다.

const value = event.currentTarget.value 랑 똑같다. 왜 저렇게 복잡하게 하냐고 물어볼수도 있는데 사실 저런식으로 한개만 만들때는 저 문법의 장점이 없다.

헌데 만약에 currentTarget안에서 value, tagName, width, id 이 4개를 가져오고 싶다고 하면 기존 문법으로는 이렇게 써야 되겠지?

const value = event.currentTarget.value;
const tagName = event.currentTarget.tagName;
const width = event.currentTarget.width;
const id = event.currentTarget.id;

이거를 이렇게 바꿔 쓰실수 있다.

const {
currentTarget: {value, tagName, width, id}
} = event;

React.FormEvent와React.FormEvent는 구글링해서 찾아서 쓰는게 맞다고 한다.

그리고 target이 아니라 currentTarget인 이유는 ReactJS TypeScript에서 이렇게 사용하기로 한거다. 그게 그거다.

Theme

TypeScript에서 테마를 쓰기위해선 몇가지 절차를 거쳐야한다.

첫번째로 src 폴더에 styled.d.ts파일을 만들자

 import "styled-components";

// and extend them!
declare module "styled-components" {
 export interface DefaultTheme {
   textColor: string;
   bgColor: string;
   btnColor: string;
 }

다음 안에다 위와 같은 코드를 기입해주자.

두번째로 src 폴더에 theme.ts파일을 만든 후

전에 했던것 처럼 코드를 작성해주자

import { DefaultTheme } from "styled-components";

export const lightTheme: DefaultTheme = {
bgColor: "white",
textColor: "black",
btnColor: "tomato",
};

export const darkTheme: DefaultTheme = {
bgColor: "black",
textColor: "white",
btnColor: "teal",
};

저번 Theme랑 큰 차이는 없지?

index에서

    <ThemeProvider theme={lightTheme}>
    <App />
  </ThemeProvider>

해주는것도 같다.

그리고 app.tsx에는

  const Container = styled.div`
  background-color: ${(props) => props.theme.bgColor};
`;

const H1 = styled.h1`
  color: ${(props) => props.theme.textColor};
`;

      <Container>
      <H1>protected</H1>
      </Container>

요런식으로.. 끝이다!

0개의 댓글