TypeScript
- JS를 기반으로 한 프로그래밍 언어
- Strongly-typed 언어: 프로그래밍 언어가 작동하기 전에 데이터의 type을 먼저 확인
JS는 type을 신경쓰지 않는다
const plus = (a, b) => a + b;
plus(2, 2);
// 4
plus(2, "hi");
// '2hi'
const user = {
firstName: "Angela",
lastName: "Davis",
role: "Professor",
};
console.log(user.name);
// undefined
데이터의 타입을 제어할 수 있을까?
const plus = (a: number, b: number) => a + b;
설치
처음부터 TypeScript로 프로젝트 시작하기
npx create-react-app my-app --template typescript
기존 프로젝트에 TypeScript 적용하기
1. 아래 설치
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
2. 확장자 변경
- .js -> .tsx (리액트에서 사용할 경우)로 변경
- .js -> .ts 리액트가 아닐 경우
3. tsconfig.json 파일 생성 및 수정
npx tsc --init
tsconfig.json 파일 수정
// tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
...
4. index.tsx 파일 수정
아래 오류 발생 시
TS2345: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'Element | DocumentFragment'.
Type 'null' is not assignable to type 'Element | DocumentFragment'.
// index.tsx
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
위 과정까지 한 경우 실행이 되는 것을 확인함
5. @types/styled-components 설치
npm i --save-dev @types/styled-components
호환이 되지 않아 설치가 안될 경우, --legacy-peer-deps를 입력하면 무시하고 설치할 수 있다
npm i --save-dev @types/styled-components --save --legacy-peer-deps
@types?
유명한 npm package들을 TypeScript가 이해할 수 있도록 TypeScript Definition이 있는 repo
🏋️♂️용어: how to TYPE
component를 type한다 = component에 type을 추가한다 = TS한테 뭐가 뭔지 설명한다
PropTypes vs TypeScript
- PropTypes는 prop이 거기 있는지 없는지 확인해주지만, 코드를 실행한 "후"에 확인 가능
- TypeScript는 코드 실행 "전"에 오류를 확인해줌
interface
interface는 object shape을 TS에게 설명해준다
playerObj의 object shape을 설명한 간단한 예시
interface PlayerShape {
name: string;
age: number;
}
const sayHello = (playerObj: PlayerShape) =>
`Hello ${playerObj.name}! You are ${playerObj.age}`;
sayHello({ name: "홍엽", age: 10 });
Circle안에 들어가는 object shape을 CircleProps로 type하고,
Circle이 리턴하는 Container의 object shape을 ContainerProps로 type 함
// Circle.tsx
import styled from "styled-components";
interface ContainerProps {
bgColor: string;
}
const Container = styled.div<ContainerProps>`
width: 200px;
height: 200px;
border-radius: 100px;
background-color: ${(props) => props.bgColor};
`;
interface CircleProps {
bgColor: string;
}
function Circle({ bgColor }: CircleProps) {
return <Container bgColor={bgColor} />;
}
export default Circle;
// App.tsx
import styled from "styled-components";
import Circle from "./Circle";
function App() {
return (
<div>
<Circle bgColor="teal" />
<Circle bgColor="tomato" />
</div>
);
}
export default App;
optional한 값을 주고 싶은 경우 ?를 사용
interface CircleProps {
bgColor: string;
borderColor?: string;
}
default한 값을 주고 싶을 경우 ??를 사용
아래의 경우에 borderColor가 없을 경우 borderColor 값은 bgColor 값 입력
function Circle({ bgColor, borderColor }: CircleProps) {
return <Container bgColor={bgColor} borderColor={borderColor ?? bgColor} />;
최종 예제 코드
// Circle.tsx
import styled from "styled-components";
interface ContainerProps {
bgColor: string;
borderColor: string;
}
const Container = styled.div<ContainerProps>`
width: 200px;
height: 200px;
border-radius: 100px;
background-color: ${(props) => props.bgColor};
border: 5px solid ${(props) => props.borderColor};
`;
interface CircleProps {
bgColor: string;
borderColor?: string;
text?: string;
}
function Circle({ bgColor, borderColor, text = "default txt" }: CircleProps) {
return (
<Container bgColor={bgColor} borderColor={borderColor ?? bgColor}>
{text}
</Container>
);
}
export default Circle;
// App.js
import styled from "styled-components";
import Circle from "./Circle";
function App() {
return (
<div>
<Circle bgColor="teal" borderColor="coral" text="new text" />
<Circle bgColor="tomato" />
</div>
);
}
export default App;
useState
- TypeScript는 초기값으로 type을 예측
- 필요한 경우 옆에 타입을 명시함으로 여러 type을 사용할 수 있음
const [counter, setCounter] = useState<number | string>(1);
setCounter("hi");
Form Event
- 이벤트 타입의 명시 방법
- 어떤 타입을 사용할지는 구글링해서 익숙해져야 함
- event의 target을 currentTarget으로 사용하는 것을 확인할 수 있었음
import { useState } from "react";
import styled from "styled-components";
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;
theme 적용 방법
npm i --save-dev @types/styled-components 설치 이후
1. styled component 확장
// styled.d.ts
import "styled-components";
// and extend them!
declare module "styled-components" {
export interface DefaultTheme {
textColor: string;
bgColor: string;
}
}
2. theme.ts 생성
// theme.ts
import { DefaultTheme } from "styled-components/dist/types";
export const lightTheme: DefaultTheme = {
bgColor: "white",
textColor: "black",
};
export const darkTheme: DefaultTheme = {
bgColor: "black",
textColor: "white",
};
3. index.tsx에서 theme 적용
// index.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { ThemeProvider } from "styled-components";
import { lightTheme } from "./theme";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<ThemeProvider theme={lightTheme}>
<App />
</ThemeProvider>
);
4. App 내에서 theme 값 사용
// App.tsx
import { useState } from "react";
import styled from "styled-components";
const Container = styled.div`
background-color: ${(props) => props.theme.bgColor};
`;
const H1 = styled.h1`
color: ${(props) => props.theme.textColor};
`;
function App() {
return (
<div>
<Container>
<H1>test</H1>
</Container>
</div>
);
}
export default App;
'React' 카테고리의 다른 글
[React] 가상화폐시세 사이트 2 - Theme 적용 (0) | 2023.08.29 |
---|---|
[React] 가상화폐시세 사이트 1 - CSS reset (0) | 2023.08.29 |
[React] styled-components (0) | 2023.08.16 |
[React 기초] 08. 예제 - Movie info (0) | 2023.08.10 |
[React 기초] 07. 예제 - Coin tracker (0) | 2023.08.10 |