Create-react-app
기준으로, 밑의 방법으로 타입스크립트를 설치한다.
1️⃣ 새로운 프로젝트
npm init react-app my-app --template typescript
2️⃣ 기존의프로젝트에 추가하려는 경우
npm i --save typescript @types/node @types/react @types/react-dom @types/jest
tsc --init
tsconfing.json 파일 생성밑의 예시들은 Functional Component 기준으로 작성되었다.
// (1) React.Fc
const Greetings: React.FC<GreetingsProps> = ({ name, mark }) => (
<div>
Hello, {name} {mark}
</div>
);
// (2) Without React.FC
const Greetings = ({ name, mark }: GreetingsProps) => (
<div>
Hello, {name} {mark}
</div>
);
function Greetings({ name, mark }: GreetingsProps) {
return (
<div>
Hello, {name} {mark}
</div>
);
}
// (1) value or null
const [info, setInformation] = useState<Information | null>(null);
// (2) object or array
type Todo = { id: number; text: string; done: boolean };
const [todos, setTodos] = useState<Todo[]>([]);
// (3) You don't need this
const [count, setCount] = useState<number>(0);
// (1) DOM
const inputRef = useRef<HTMLInputElement>(null);
return <input type="text" id="todo-text" ref={inputRef} />
// (2)
const id = useRef<number>(0);
사용하려는 자바스크립트 라이브러리가 타입스크립트를 지원한다면, 라이브러리 이름 앞에
@types
를 붙여서 설치하면 된다. (예시:npm i @/typesreact-router-dom
)
npm i styled-componens @types/styled-commponents
Prop의 Type 설정하기
// 1️⃣ type or interface
type BtnWrapperProps = {
correct: boolean;
};
export const BtnWrapper = styled.div<BtnWrapperProps>`
background: ${({ correct }) => correct ? 'green' : 'red' };
`;
// 2️⃣ generic
export const BtnWrapper = styled('div')<{ correct: boolean }>`
background: ${({ correct }) => correct ? 'green' : 'red' };
`;
// 3️⃣ css
/* cssprop.d.ts 파일생성후,
import * as types from 'styled-components/cssprop';
*/
import styled, { css } from 'styled-components';
const ColorPaletteContainer = styled('div')<{ isInputField?: string }>`
max-width: 128px;
${({ isInputField }) =>
isInputField &&
css`
bottom: 80px;
`}
`;
(참고)
css
안에서 ${props => props.isPinned ? 'black' : 'white'}
와 같이 조건적으로 스타일을 적용할 경우 에러가 났는데 이 때 props
에 타입을 설정해주니 해결되었다.
리액트를 사용하다보면 custom props를 자주 사용하게 된다. Custom Html Attr(props)을 사용하는 방법을 알아보자
src/types/index.d.ts
파일을 생성하고 사용할 props를 정의해준 다음, 평소와 같이 사용하면 된다.
d.ts
파일은 모듈에 대한 타입스크립트 타입 정보를 제공하는 파일이다. 예를 들어, 이미지를 import 하고 싶을 때,image.d.ts
파일을 생성하고declare module '*.jpg';
와 같이 정의하면 된다.
// index.d.ts
import 'react';
declare module 'react' {
export interface HTMLAttributes<T> {
path?: any; // Custom props
}
}
컴포넌트에서 사용하기
// Content.js
return (
<Wrapper>
<Content path={path === 'keep' ? path : null} />
</Wrapper>
);
(참고)
index.d.ts에서 props를 정의하고 나면 계속 module has no exported member react
라는 에러가 났는데 props의 타입이 틀려서 그랬던 것 같다. path={path === 'keep' ? path : null}
의 경우 일단 any
로 바꾸었더니 정상적으로 작동했다.
RouteComponentProps
을 import해서 타입으로 지정해준다.
import { withRouter, RouteComponentProps } from 'react-router-dom'; // (*)
const Logo = ({ location }: RouteComponentProps) => { // (*)
return <Content />
};
export default withRouter(Logo);
match
속성을 사용한다면, 아래와 같이 사용하면 된다.
import { RouteComponentProps } from 'react-router-dom';
interface MatchParams {
id: string; // params
}
const LabelPage = ({ match }: RouteComponentProps<MatchParams>) => {
const { labelName } = match.params;
// ...
}
// store/reducer/index.tsx
const rootReducer = combineReducers({
view,
notes,
});
export default rootReducer;
export type RootState = ReturnType<typeof rootReducer>; // (*)
// Using it
import { RootState } from 'store/reducers/index';
const labels = useSelector((state: RootState) => state.notes.labels);
setState
를 props
로 자식 컴포넌트에게 전달할 경우
// Parent.tsx
interface Note {
title: string;
content: string;
};
const Parent = () => {
const [note, setNote] = useState<Note>({ title: '', content: '' });
return <Child setNote={setNote} />
}
// Child.tsx
import React, { Dispatch, SetStateAction } from 'react'; // (*)
import Note from 'components/Parent/Parent';
interface ChildProp {
setNote: Dispatch<SetStateAction<Note>> // (*)
}
useState
를 자주 자식 컴포넌트에게 넘겨줄 경우, type Dispatcher<S> = Dispatch<SetStateAction<S>>
와 같이 type alias
를 작성할 수 있다.