CRA๋ก typescript ์์ํ ์
npx create-react-app my-app --template typescript
๊ธฐ์กด javascript๋ก ์์ฑ๋ React ํ๋ก์ ํธ์ typescript๋ฅผ ์ถ๊ฐํ๊ฒ ๋ ๊ฒฝ์ฐ
npm install typescript @types/node @types/react @types/react-dom @types/jest @types/react-router-dom
# ๋ฆฌ๋์ค ํดํท
npm install --save-dev @reduxjs/toolkit @types/react-redux
# ์คํ์ผ๋ ์ปดํฌ๋ํธ
npm install @types/styled-components
# ์คํ ๋ฆฌ๋ถ
npm install --save-dev @storybook/preset-typescript
# tsconfig.json ์์ฑ
npx tsc --init
# npm install @types/react๋ฅผ ํด์คฌ๋๋ฐ๋ ์ ๋ ์ ๋ค์ ์ค์นํจ
# npm install --save-dev @types/react
"compilerOptions": {
"jsx": "react",
"types": ["styled-components"],
}
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
srcํด๋ ์์ custom.d.tsํ์ผ ์์ฑ
/* src/custom.d.ts */
declare module "*.svg" {
const content: any;
export default content;
}
declare module "*.png" {
const content: any;
export default content;
}
tsconfig.json์ ๋ด์ฉ ์ถ๊ฐ
/* tsconfig.json */
"include": ["src", "src/custom.d.ts"],
"exclude": ["node_modules"]
Store/index.ts
/* Store/index.ts */
import { legacy_createStore as createStore, combineReducers } from "redux";
import { todoReducer } from "../Reducers";
const rootReducers = combineReducers({ todoReducer });
export type RootState = ReturnType<typeof rootReducers>; // ์ฌ๊ธฐ ์ถ๊ฐ
const store = createStore(rootReducers);
export default store;
Actions/action.tsx
โ ํ์ ์ง์ ๋ฐ as ์ง์
export const CREATE: string = "create" as const;
โ enum์ผ๋ก ํ์ ์ง์
export enum ActionTypes {
CREATE = "create",
REMOVE = "remove",
TOGGLE = "toggle",
DOING_FILTER = "doingFilter",
COMPLE_FILTER = "compleFilter",
CHANGE_TEXT = "changeText",
}
โ ์ก์ ํจ์์ ๋ง๊ฒ ๋ฆฌํด ํ์ ์ง์
// ์ธํฐํ์ด์ค
export interface ITodos {
id: number;
text: string;
done: boolean;
}
interface ICreateAction {
type: ActionTypes.CREATE;
payload: ITodos;
}
.....
// ์ก์
ํจ์
export const create = (todo: ITodos): ICreateAction => {
return {
type: ActionTypes.CREATE,
payload: todo,
};
};
.....
// ์ก์
ํ์
๋ค
export type TTodoAction = ICreateAction | IRemoveAction | IToggleAction | IDoingFilterAction | ICompleFilterAction | IChangeTextAction;
Reducers/initialState.js
mport { ITodos } from "../Actions/action";
export interface ITodosArr {
todos: ITodos[];
doing: ITodos[];
completed: ITodos[];
}
export const initialState: ITodosArr = {
todos: [
{
id: 1,
text: "๊ฐ์ง๋๊ฒ ์จ์ฌ๊ธฐ",
done: true,
},
.....
Reducers/index.js
export const todoReducer = (state: ITodosArr = initialState, action: TTodoAction) => {
switch (action.type) {
case CREATE:
const createPayload = action.payload as ITodos; // payload ํ์
์ ๋ถ๊ธฐ ์ฒ๋ฆฌ
return Object.assign({}, state, { todos: [...state.todos, createPayload], doing: [...state.doing, createPayload] });
case REMOVE:
const removePayload = action.payload as { id: number }; // payload ํ์
์ ๋ถ๊ธฐ ์ฒ๋ฆฌ
const removeTodos = state.todos.filter((el: ITodos) => el.id !== removePayload.id);
.....
case CHANGE_TEXT:
const changeTextPayload = action.payload as { id: number; text: string }; // payload ํ์
์ ๋ถ๊ธฐ ์ฒ๋ฆฌ
const changeTodos = state.todos.map((el: ITodos) => {
if (el.id === changeTextPayload.id) return { ...el, text: changeTextPayload.text };
return el;
});
.....
React.ReactNode
export interface ITemplateProps {
children: React.ReactNode;
}
const TodoTemplateNotice = ({ children }: ITemplateProps) => {
return (
<TodoTemplateBlock>
<RealTemplateBlock>{children}</RealTemplateBlock>
</TodoTemplateBlock>
);
};
MouseEvent
useEffect(() => {
const outInput = (e: MouseEvent) => {
const node = e.target as Node;
if (isEditable && inputRef.current && !inputRef.current.contains(node)
.....
React.ChangeEvent<HTMLInputElement>
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
};
React.FormEvent
const onSubmit = (e: React.FormEvent) => {
e.preventDefault();
}
<HTMLInputElement>
const inputRef = useRef<HTMLInputElement>(null);
React.Dispatch<React.SetStateAction<ํ์
>>
interface IAdcButtonProps {
setBtnTxt: React.Dispatch<React.SetStateAction<string>>;
setAll: React.Dispatch<React.SetStateAction<boolean>>;
setFilterTxt: React.Dispatch<React.SetStateAction<string>>;
}
const AdcButton = ({ setBtnTxt, setAll, setFilterTxt }: IAdcButtonProps) => {