An open API service indexing awesome lists of open source software.

https://github.com/typescript-cheatsheets/react-typescript-cheatsheet-kr


https://github.com/typescript-cheatsheets/react-typescript-cheatsheet-kr

Last synced: 4 months ago
JSON representation

Awesome Lists containing this project

README

        

# React+TypeScript Cheatsheets ํ•œ๊ตญ์–ดํŒ ๐Ÿ‡ฐ๐Ÿ‡ท

TypeScript์— ์ž…๋ฌธํ•˜๋Š” React ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ์น˜ํŠธ์‹œํŠธ(Cheetsheets)

---


react + ts logo

[**์›น ๋‹คํ๋จผํŠธ**](https://react-typescript-cheatsheet.netlify.app/docs/basic/setup) |
[**์˜์–ดํŒ**](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet-es) |
[ํ”„๋กœ์ ํŠธ์— ๊ธฐ์—ฌํ•˜๊ธฐ]() |
[์งˆ๋ฌธํ•˜๊ธฐ]()

:wave: ๋ณธ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋Š” [@ryan_kim_kr](https://twitter.com/ryan_kim_kr)์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋‹˜์ด React์™€ ํ•จ๊ป˜ TypeScript๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๊ณ ์ž ํ•˜์‹œ๋‹ค๋‹ˆ ์ •๋ง ๊ธฐ์œ ์†Œ์‹์ด๊ตฐ์š”! ์ž˜๋ชป๋œ ๋ถ€๋ถ„์ด ๋ฐœ๊ฒฌ๋˜์–ด ์ˆ˜์ •์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜ ๋ˆ„๋ฝ๋œ ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ๊ฐœ์„  ๋˜์–ด์•ผ ํ•  ์‚ฌํ•ญ์„ [์ด์Šˆ ๋“ฑ๋ก](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet-kr/issues/new)ํ•ด ์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค. :+1:

---

[![All Contributors](https://img.shields.io/github/contributors/typescript-cheatsheets/react-typescript-cheatsheet?color=orange&style=flat-square)](/COLABORADORES.md)

# All React + TypeScript Cheatsheets

- [๊ธฐ์ดˆ ์น˜ํŠธ์‹œํŠธ(The Basic Cheatsheet)]()๋Š” React ๊ฐœ๋ฐœ์ž๊ฐ€ React app์—์„œ TS ์‚ฌ์šฉ์„ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์— ๋„์›€์„ ์ฃผ๊ธฐ ์œ„ํ•œ ๋‚ด์šฉ์ด ์ฃผ๋ฅผ ์ด๋ฃน๋‹ˆ๋‹ค.
- ๋ชจ๋ฒ” ์‚ฌ๋ก€(Best Practices)๋ผ๊ณ  ์—ฌ๊ฒจ์ง€๋Š”, ๋ณต์‚ฌ + ๋ถ™์—ฌ๋„ฃ๊ธฐ ๊ฐ€๋Šฅํ•œ ์˜ˆ์‹œ
- ๊ธฐ๋ณธ์ ์ธ TS Types ์‚ฌ์šฉ๋ฒ•๊ณผ ์„ค์ • ๋ฐฉ๋ฒ•
- ์ž์ฃผ ๋ฌป๋Š” ์งˆ๋ฌธ(FAQ)์— ๋Œ€ํ•œ ๋‹ต๋ณ€
- Generic type logic์€ ๊นŠ์ด ๋‹ค๋ฃจ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ ๋Œ€์‹ , ์ดˆ์‹ฌ์ž๋“ค์„ ์œ„ํ•ด ๊ฐ„๋‹จํ•œ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๊ธฐ์ˆ ๋“ค์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.
- ๊ธฐ์ดˆ ์น˜ํŠธ์‹œํŠธ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ TypeScript์— ๋Œ€ํ•ด ๋„ˆ๋ฌด ๋งŽ์€ ๊ณต๋ถ€๋ฅผ ํ•˜์ง€ ์•Š๊ณ ์„œ๋„ **์‹œ๊ฐ„ ํšจ์œจ์ **์œผ๋กœ React ๊ฐœ๋ฐœ์— TypeScript๋ฅผ ๋น ๋ฅด๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•๋Š” ๋ฐ ๊ทธ ๋ชฉ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
- [๊ณ ๊ธ‰ ์น˜ํŠธ์‹œํŠธ(The Advanced Cheatsheet)]()๋Š” ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ type utilities/functions/render prop/higher order copmonents ๋˜๋Š” TS+React ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•ด generic types์˜ ๊ณ ๊ธ‰ ์‚ฌ์šฉ๋ฒ•์— ๋Œ€ํ•œ ์ดํ•ด๋ฅผ ๋•์Šต๋‹ˆ๋‹ค.
- ์ „๋ฌธ์ ์ธ ๊ฐœ๋ฐœ์ž๋“ค์„ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ํŒ๊ณผ ์š”๋ น๋“ค์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.
- DefinitelyTyped์— ๊ธฐ์—ฌํ•˜๊ธฐ ์œ„ํ•œ ์กฐ์–ธ์„ ๋“œ๋ฆฝ๋‹ˆ๋‹ค.
- ๊ณ ๊ธ‰ ์น˜ํŠธ์‹œํŠธ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ TypeScript๋ฅผ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•๋Š” ๋ฐ ๊ทธ ๋ชฉ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
- [๋งˆ์ด๊ทธ๋ ˆ์ดํŒ… ์น˜ํŠธ์‹œํŠธ(The Migrating Cheatsheet)]()๋Š” ๋Œ€๊ทœ๋ชจ ์ฝ”๋“œ๋ฒ ์ด์Šค๋ฅผ JS ๋˜๋Š” Flow์—์„œ TypsScript๋กœ ์ ์ง„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๊ฒฝํ—˜์ž์˜ ์กฐ์–ธ์„ ์–ป๋Š”๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค.
- ์šฐ๋ฆฌ๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ํ•˜๋„๋ก ์„ค๋“ํ•˜๋ ค๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ฉฐ, ์ด๋ฏธ ๊ทธ๋ ‡๊ฒŒ ํ•˜๊ณ ์ž ๊ฒฐ์ •ํ•œ ์‚ฌ๋žŒ๋“ค์„ ๋•๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.
- โš ๏ธ ์ด ์น˜ํŠธ์‹œํŠธ๋Š” ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค์–ด์ง„ ์น˜ํŠธ์‹œํŠธ ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋„์›€์„ ์ฃผ๊ณ ์ž ํ•˜๋Š” ๋ชจ๋“  ๋ถ„๋“ค์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.
- [HOC ์น˜ํŠธ์‹œํŠธ(The HOC Cheatsheet)]()๋Š” ์˜ˆ์‹œ์™€ ํ•จ๊ป˜ HOC๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
- [Generics](https://www.typescriptlang.org/docs/handbook/2/generics.html)์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ ์„ ํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
- โš ๏ธ ์ด ์น˜ํŠธ์‹œํŠธ๋Š” ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค์–ด์ง„ ์น˜ํŠธ์‹œํŠธ ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋„์›€์„ ์ฃผ๊ณ ์ž ํ•˜๋Š” ๋ชจ๋“  ๋ถ„๋“ค์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

---

## ๊ธฐ์ดˆ ์น˜ํŠธ์‹œํŠธ (Basic Cheatsheet)

### ๊ธฐ์ดˆ ์น˜ํŠธ์‹œํŠธ ๋ชฉ์ฐจ

๋ชฉ์ฐจ ํ™•์žฅํ•˜๊ธฐ

- [์„น์…˜ 1: React์— TypeScript ์„ค์ •ํ•˜๊ธฐ]()

- [์ „์ œ์กฐ๊ฑด]()

### ์„น์…˜ 1: React์— TypeScript ์„ค์ •ํ•˜๊ธฐ

#### ์‹œ์ž‘ํ•˜๊ธฐ ์ „ ํ•„์š”ํ•œ ์‚ฌํ•ญ

1. [React](https://reactjs.org)์— ๋Œ€ํ•œ ์ถฉ๋ถ„ํ•œ ์ดํ•ด
2. [TypeScript Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html)์ฃผ์ œ์— ๋Œ€ํ•œ ์ดํ•ด ([2ality's guide](http://2ality.com/2018/04/type-notation-typescript.html)๋ฅผ ์•Œ๊ณ ์žˆ์œผ๋ฉด ๋ฌธ์„œ๋ฅผ ์ดํ•ดํ•˜๋Š”๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ TypeScript๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๋Š” ๋ถ„์ด๋ผ๋ฉด,[chibicodeโ€™s tutorial](https://ts.chibicode.com/todo/)๋ฅผ ์ฐธ๊ณ ํ•ด ๋ณด์„ธ์š”.)
3. [the TypeScript section in the official React docs](https://reactjs.org/docs/static-type-checking.html#typescript) ์ฝ๊ธฐ
4. [the React section of the new TypeScript playground](http://www.typescriptlang.org/play/index.html?jsx=2&esModuleInterop=true&e=181#example/typescript-with-react) ์ฝ๊ธฐ (์„ ํƒ์‚ฌํ•ญ: [the playground's](http://www.typescriptlang.org/play/index.html) Example Section์˜ 40+ examples ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•ด ๋ณด๊ธฐ)

์ด ๊ฐ€์ด๋“œ๋Š” ๋…์ž๊ฐ€ ๊ฐ€์žฅ ์ตœ์‹  ๋ฒ„์ „์˜ TypeScript์™€ React๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด์ „ ๋ฒ„์ „์— ๋Œ€ํ•œ ์‚ฌํ•ญ์€ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ `` ํƒœ๊ทธ๋กœ ํ™•์ธ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

#### VS Code ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ(Extensions)

- ๋ฆฌํŽ™ํ† ๋ง ๋ณด์กฐ https://marketplace.visualstudio.com/items?itemName=paulshen.paul-typescript-toolkit
- R+TS Code Snippets (์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์ด ์žˆ์Šต๋‹ˆ๋‹ค...)
- https://marketplace.visualstudio.com/items?itemName=infeng.vscode-react-typescript
- https://www.digitalocean.com/community/tutorials/the-best-react-extension-for-vs-code
- TypeScript ๊ณต์‹ ํ™•์žฅํ”„๋กœ๊ทธ๋žจ https://code.visualstudio.com/docs/languages/typescript

#### React + TypeScript ์ž…๋ฌธ์ž ํ‚คํŠธ

Cloud setups:

- [TypeScript Playground with React](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcA5FDvmQNwCwAUKJLHAN5wCuqWAyjMhhYANFx4BRAgSz44AXzhES5Snhi1GjLAA8W8XBAB2qeAGEInQ0KjjtycABsscALxwAFAEpXAPnaM4OANjeABtA0sYUR4Yc0iAXVcxPgEhdwAGT3oGAOTJaXx3L19-BkDAgBMIXE4QLCsAOhhgGCckgAMATQsgh2BcAGssCrgAEjYIqwVmutR27MC5LM0yuEoYTihDD1zAgB4K4AA3H13yvbAfbs5e-qGRiYspuBmsVD2Aekuz-YAjThgMCMcCMpj6gxcbGKLj8MTiVnck3gAGo4ABGTxyU6rcrlMF3OB1H5wT7-QFGbG4z6HE65ZYMOSMIA)๋Š” ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  Types๋ฅผ ๋””๋ฒ„๊น…๋งŒ ํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- [CodeSandbox](http://ts.react.new) - cloud IDE, ๋งค์šฐ ๋น ๋ฅธ ๋ถ€ํŒ… ์†๋„๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
- [Stackblitz](https://stackblitz.com/edit/react-typescript-base) - cloud IDE, ๋งค์šฐ ๋น ๋ฅธ ๋ถ€ํŒ… ์†๋„๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

Local dev setups:

- [Next.js](https://nextjs.org/docs/basic-features/typescript): `npx create-next-app -e with-typescript` ๋ช…๋ น์–ด๋Š” ์ƒˆ๋กœ์šด NextJS ํ”„๋กœ์ ํŠธ๋ฅผ ํ˜„์žฌ ํด๋”์— ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
- [Create React App](https://facebook.github.io/create-react-app/docs/adding-typescript): `npx create-react-app name-of-app --template typescript` ๋ช…๋ น์–ด๋Š” ์ƒˆ๋กœ์šด NextJS ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒˆ๋กœ์šด ํด๋”์— ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
- [Vite](https://vitejs.dev/): `npm create vite@latest my-react-ts-app -- --template react-ts`
- [Meteor](https://guide.meteor.com/build-tool.html#typescript): `meteor create --typescript name-of-my-new-typescript-app`
- [Ignite](https://github.com/infinitered/ignite#use-ignite-andross-infinite-red-andross-boilerplate) for React Native: `ignite new myapp`
- [TSDX](https://tsdx.io/): `npx tsdx create mylib` ๋ช…๋ น์–ด๋Š” React+TS _๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ_ ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. (in future: [TurboRepo](https://twitter.com/jaredpalmer/status/1346217789942591488))

๋‹ค๋ฅธ ๋„๊ตฌ๋“ค

์•„์ง ๋ณด์™„์ด ํ•„์š”ํ•˜์ง€๋งŒ ํ™•์ธํ•ด ๋ณผ ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š” ๋„๊ตฌ๋“ค:

- [Snowpack](): `npx create-snowpack-app my-app --template app-template-react-typescript`
- [Docusaurus v2](https://v2.docusaurus.io/docs/installation) with [TypeScript Support](https://v2.docusaurus.io/docs/typescript-support)
- [Parcel](https://v2.parceljs.org/languages/typescript/)
- [JP Morgan's `modular`](https://github.com/jpmorganchase/modular): CRA + TS + Yarn Workspaces toolkit. `yarn create modular-react-app `

Manual setup:

- [Basarat's guide](https://github.com/basarat/typescript-react/tree/master/01%20bootstrap)๋Š” React + TypeScript + Webpack + Babel ์„ **์ˆ˜๋™์œผ๋กœ ์„ค์ •** ํ•  ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- ํŠนํžˆ, `@types/react`์™€ `@types/react-dom`๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ([์ต์ˆ™ํ•˜์ง€ ์•Š์€ ๋‚ด์šฉ์ด๋ผ๋ฉด DefinitelyTyped project ์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณด์„ธ์š”.](https://definitelytyped.org/))
- ๋˜ํ•œ ๋งŽ์€ React + TypeScript bolierplates๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค. [์šฐ๋ฆฌ์˜ ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค ๋ฆฌ์ŠคํŠธ](https://react-typescript-cheatsheet.netlify.app/docs/basic/recommended/resources/)๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.

#### ๋น„๋””์˜ค ํŠœํ† ๋ฆฌ์–ผ

์•„๋ž˜์˜ 7๋ถ€๋กœ ๊ตฌ์„ฑ๋œ "React Typescript Course" ๋น„๋””์˜ค ์‹œ๋ฆฌ์ฆˆ๋ฅผ ํ†ตํ•ด TypeScript with React์— ๋Œ€ํ•œ ์†Œ๊ฐœ๋ฅผ ๋“ค์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


react typescript course video series

### Section 2: ์‹œ์ž‘ํ•˜๊ธฐ

#### ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ

ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š” `props`๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๊ณ  JSX element๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜๋กœ ์ž‘์„ฑ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

```tsx
// props์˜ ํƒ€์ž… ์ •์˜ - ๋” ๋งŽ์€ ์˜ˆ์‹œ๋Š” "์ปดํฌ๋„ŒํŠธ Props ํƒ€์ดํ•‘"์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
type AppProps = {
message: string;
}; /* export ํ•œ๋‹ค๋ฉด consumer๊ฐ€ extendํ•  ์ˆ˜ ์žˆ๋„๋ก `interface`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. */

// ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•; return type์€ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค.
const App = ({ message }: AppProps) =>

{message}
;

// ์‹ค์ˆ˜๋กœ ๋‹ค๋ฅธ ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•˜์˜€์„ ๋•Œ ์—๋Ÿฌ๊ฐ€ raise ๋˜๋„๋ก return type์„ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
const App = ({ message }: AppProps): JSX.Element =>

{message}
;

// type ์„ ์–ธ์„ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ์„ ์–ธ์— ํฌํ•จ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.;์ด ๋ฐฉ๋ฒ•์€ prop types์— ์ด๋ฆ„์„ ๋ถ™์ด์ง€ ์•Š์•„๋„ ๋˜์ง€๋งŒ ์ฝ”๋“œ๊ฐ€ ๋ฐ˜๋ณต๋ฉ๋‹ˆ๋‹ค.
const App = ({ message }: { message: string }) =>

{message}
;
```

> Tip: type destructure ์„ ์–ธ์„ ์œ„ํ•ด [Paul Shen's VS Code Extension](https://marketplace.visualstudio.com/items?itemName=paulshen.paul-typescript-toolkit)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ([keyboard shortcut](https://twitter.com/_paulshen/status/1392915279466745857?s=20)์„ ์ถ”๊ฐ€ ํ•˜์„ธ์š”.)

React.FC๊ฐ€ ๊ถŒ์žฅ๋˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ผ๊นŒ์š”? React.FunctionComponent/React.VoidFunctionComponent๋Š” ์–ด๋–ค๊ฐ€์š”?

React+TypeScript codebases์—์„œ ๋‹ค์Œ ๋ณด์•˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

```tsx
const App: React.FunctionComponent<{ message: string }> = ({ message }) =>

{message}
;
```

ํ•˜์ง€๋งŒ, ํ˜„์žฌ `React.FunctionComponent` (๋˜๋Š” ๊ฐ„๋žตํ•˜๊ฒŒ ์จ์„œ `React.FC`)๋Š” [๊ถŒ์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ](https://github.com/facebook/create-react-app/pull/8177)์— ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์ด ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ด ์ฃผ์ œ์— ๋Œ€ํ•œ ๋ฏธ๋ฌ˜ํ•œ ์˜๊ฒฌ ์ฐจ์ด๊ฐ€ ์žˆ์„ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๋งŒ์•ฝ ์ด ์˜๊ฒฌ์— ๋™์˜ํ•˜๊ณ  `React.FC`๋ฅผ ๋‹น์‹ ์˜ ์ฝ”๋“œ๋ฒ ์ด์Šค์—์„œ ์ œ๊ฑฐํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, [์ด jscodeshift codemond](https://github.com/gndelia/codemod-replace-react-fc-typescript)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

"์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜" ๋ฒ„์ „๊ณผ์˜ ์ฐจ์ด์ ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

- `React.FunctionComponent`๋Š” return type์„ ๋ช…์‹œ์ ์œผ๋กœ ๋ฐํž™๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜ ๋ฒ„์ „์€ ์•”์‹œ์ ์ž…๋‹ˆ๋‹ค(๋˜๋Š” ์ถ”๊ฐ€์ ์ธ ์–ด๋…ธํ…Œ์ด์…˜(annotation)์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค).

- `displayName`, `propTypes`, ๊ทธ๋ฆฌ๊ณ  `defaultProps`์™€ ๊ฐ™์€ static properties๋ฅผ ์œ„ํ•œ ์ž๋™์™„์„ฑ(autocomplete)๊ณผ ํƒ€์ž… ์ฒดํฌ(Typechecking)๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

- `React.FunctionComponent`์™€ ํ•จ๊ป˜ `defaultProps`์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ๋ช‡ ๊ฐ€์ง€ ์•Œ๋ ค์ง„ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. [๋ฌธ์ œ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ](https://github.com/typescript-cheatsheets/react/issues/87)์„ ํ™•์ธํ•˜์„ธ์š”. ์šฐ๋ฆฌ๋Š” ๊ฐœ๋ฐœ์ž๋‹˜์ด ์ฐพ์•„๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ณ„๊ฐœ์˜ `defaultProps` ์„น์…˜์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

- [React 18 type ์—…๋ฐ์ดํŠธ](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56210) ์ด์ „์—๋Š”, `React.FunctionComponent`์ด `children`์— ๋Œ€ํ•œ ์•”์‹œ์ ์ธ ์ •์˜(implicit definition)๋ฅผ ์ œ๊ณตํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์—ด๋ค ํ† ๋ก  ๊ณผ์ •์„ ๊ฑฐ์ณค๊ณ  ๊ฒฐ๊ณผ์ ์œผ๋กœ [`React.FC`๊ฐ€ Create React App TypeScript template์—์„œ ์ œ๊ฑฐ](https://github.com/facebook/create-react-app/pull/8177)๋œ ์ด์œ  ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

```tsx
// React 18 types ์ด์ „
const Title: React.FunctionComponent<{ title: string }> = ({ children, title }) => (

{children}

);
```

(Deprecated)React.VoidFunctionComponent ๋˜๋Š” React.VFC ์‚ฌ์šฉํ•˜๊ธฐ

[@types/react 16.9.48](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/46643)์—์„œ, `React.VoidFunctionComponent` ๋˜๋Š” `React.VFC` type์€ `children`์„ ๋ช…์‹œ์ ์œผ๋กœ ํƒ€์ดํ•‘(typing) ํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ, `React.VFC`์™€ `React.VoidFunctionComponent`๋Š” React 18 (https://github.com/DefinitelyTyped/DefinitelyTyped/pull/59882) ์—์„œ ๋”์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค(deprecated). ๋”ฐ๋ผ์„œ ์ด ์ž„์‹œ๋ฐฉํŽธ์€ React 18+ ์—์„œ ๋”์ด์ƒ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋‚˜ `React.FC`๋ฅผ ์‚ฌ์šฉํ•ด ์ฃผ์„ธ์š”.

```ts
type Props = { foo: string };

// ์ง€๊ธˆ์€ ๊ดœ์ฐฎ์ง€๋งŒ, ๋ฏธ๋ž˜์—๋Š” ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
const FunctionComponent: React.FunctionComponent = ({ foo, children }: Props) => {
return (


{foo} {children}

); // OK
};

// ์ง€๊ธˆ์€ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ณ , ๋ฏธ๋ž˜์—๋Š” ๋”์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์„๊ฒƒ์ž…๋‹ˆ๋‹ค.(Deprecated)
const VoidFunctionComponent: React.VoidFunctionComponent = ({ foo, children }) => {
return (


{foo}
{children}

);
};
```

- _๋ฏธ๋ž˜์—๋Š”_, props๋ฅผ ์ž๋™์œผ๋กœ `readonly` ๋ผ๊ณ  ํ‘œ์‹œํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, props ๊ฐ์ฒด๊ฐ€ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฆฌ์ŠคํŠธ์—์„œ destructure ๋œ๋‹ค๋ฉด, ์ด๊ฒƒ์€ ์˜๋ฏธ์—†๋Š” ํ–‰๋™ ์ž…๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์—๋Š” ์–ด๋–ค syntax๋ฅผ ์‚ฌ์šฉํ•˜๋˜์ง€ ํฐ ์ฐจ์ด๊ฐ€ ์—†์ง€๋งŒ, `React.FunctionComponent`์˜ ๋ณด๋‹ค ๋ช…์‹œ์ ์ธ ํŠน์„ฑ์„ ์„ ํ˜ธํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฃผ์˜ํ•ด์•ผ ํ•  ์‚ฌํ•ญ

๋‹ค์Œ์˜ ํŒจํ„ด์€ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. :

**์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง(conditional rendering)**

```tsx
const MyConditionalComponent = ({ shouldRender = false }) => (shouldRender ?

: false); // JS ์—์„œ๋„ ์ด๋ ‡๊ฒŒ ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.
const el = ; // ์—๋Ÿฌ๋ฅผ throw ํ•ฉ๋‹ˆ๋‹ค.
```

์ด ํŒจํ„ด์ด ์ง€์›๋˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ์˜ ํ•œ๊ณ„ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š” JSX expression ๋˜๋Š” `null` ์ด์™ธ์˜ ๋‹ค๋ฅธ ์–ด๋–ค ๊ฒƒ๋„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์ด ๋ฐ˜ํ™˜๋œ๋‹ค๋ฉด ํ•ด๋‹น ํƒ€์ž…์€ `Element`์— ํ• ๋‹น๋  ์ˆ˜ ์—†๋‹ค๋Š” ์—๋Ÿฌ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๊ฒŒ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ("{the other type} is not assignable to `Element`.")

**Array.fill**

```tsx
const MyArrayComponent = () => Array(5).fill(

);
const el2 = ; // throws an error
```

์•„์‰ฝ๊ฒŒ๋„ ํ•จ์ˆ˜์˜ ํƒ€์ž…์„ annotate ํ•˜๋Š” ๊ฒƒ์€ ์•„๋ฌด๋Ÿฐ ๋„์›€์ด ๋˜์ง€ ์•Š์„๊ฒƒ์ž…๋‹ˆ๋‹ค. React๊ฐ€ ์ง€์›ํ•˜๋Š” ๋‹ค๋ฅธ ํŠน๋ณ„ํ•œ ํƒ€์ž…(exotic type)์„ ๋ฐ˜ํ™˜ํ•˜๊ณ ์ž ํ•œ๋‹ค๋ฉด ํƒ€์ž… ํ‘œ๋ช…(type assertion)์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. :

```tsx
const MyArrayComponent = () => Array(5).fill(

) as any as JSX.Element;
```

[์—ฌ๊ธฐ์„œ @ferdaber ์˜ ์„ค๋ช…์„ ํ™•์ธํ•ด๋ณด์„ธ์š”](https://github.com/typescript-cheatsheets/react/issues/57).

#### Hooks

Hook์€ [`@types/react` v16.8 ์ด์ƒ๋ถ€ํ„ฐ ์ง€์›๋ฉ๋‹ˆ๋‹ค](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/a05cc538a42243c632f054e42eab483ebf1560ab/types/react/index.d.ts#L800-L1031).

#### useState

ํƒ€์ž… ์ถ”๋ก (Type inference)์€ ๊ฐ„๋‹จํ•œ ๊ฐ’๋“ค์— ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค:

```tsx
const [state, setState] = useState(false);
// `state` ๋Š” boolean ์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค.
// `setState` ๋Š” boolean ๊ฐ’ ๋งŒ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.
```

ํƒ€์ž… ์ถ”๋ก ์— ๋ณต์žกํ•œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด [์ถ”๋ก ๋œ ํƒ€์ž…(Inferred Types) ์‚ฌ์šฉํ•˜๊ธฐ](https://react-typescript-cheatsheet.netlify.app/docs/basic/troubleshooting/types/#using-inferred-types) ๋„ ํ™•์ธํ•ด๋ณด์„ธ์š”.

ํ•˜์ง€๋งŒ ๋งŽ์€ hook ๋“ค์€ null ๊ฐ™์€ ๊ฐ’๋ฅผ ๋””ํดํŠธ ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™” ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ป๊ฒŒ ํƒ€์ž…์„ ์ง€์ •ํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ช…์‹œ์ ์œผ๋กœ ํƒ€์ž…์„ ์„ ์–ธํ•˜๊ณ , union type์„ ์‚ฌ์šฉํ•˜์„ธ์š”.:

```tsx
const [user, setUser] = useState(null);

// later...
setUser(newUser);
```

๋งŒ์•ฝ useState์„ค์ • ์งํ›„์— state๊ฐ€ ์ดˆ๊ธฐํ™”๋˜๊ณ  ๊ทธ ์ดํ›„์— ํ•ญ์ƒ ๊ฐ’์„ ๊ฐ€์ง„๋‹ค๋ฉด, ํƒ€์ž… ํ‘œ๋ช…(type assertions)์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

```tsx
const [user, setUser] = useState({} as User);

// later...
setUser(newUser);
```

์ด ๋ฐฉ๋ฒ•์€ ์ผ์‹œ์ ์œผ๋กœ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ `{}`๊ฐ€ `User`์˜ type์ด๋ผ๊ณ  "๊ฑฐ์ง“๋ง" ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ํ›„์— `user` state๋ฅผ ์„ค์ •ํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋‚˜๋จธ์ง€ ์ฝ”๋“œ๊ฐ€ `user`๋Š” `User` ํƒ€์ž…์ด๋ผ๋Š” ์‚ฌ์‹ค์— ์˜์กด๊ณ  ์ด๊ฒƒ์€ ๋Ÿฐํƒ€์ž… ์—๋Ÿฌ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

#### useReducer

Reducer actions๋ฅผ ์œ„ํ•ด [Discriminated Unions](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#discriminated-unions)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. reducer์˜ return type์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ return type์„ ์ถ”๋ก ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

```tsx
import { useReducer } from "react";

const initialState = { count: 0 };

type ACTIONTYPE = { type: "increment"; payload: number } | { type: "decrement"; payload: string };

function reducer(state: typeof initialState, action: ACTIONTYPE) {
switch (action.type) {
case "increment":
return { count: state.count + action.payload };
case "decrement":
return { count: state.count - Number(action.payload) };
default:
throw new Error();
}
}

function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
dispatch({ type: "decrement", payload: "5" })}>-
dispatch({ type: "increment", payload: 5 })}>+
>
);
}
```

[TypeScript Playground์—์„œ ๋ณด๊ธฐ](https://www.typescriptlang.org/play?#code/LAKFEsFsAcHsCcAuACAVMghgZ2QJQKYYDGKAZvLJMgOTyEnUDcooRsAdliuO+IuBgA2AZUQZE+ZAF5kAbzYBXdogBcyAAwBfZmBCIAntEkBBAMIAVAJIB5AHLmAmgAUAotOShkyAD5zkBozVqHiI6SHxlagAaZGgMfUFYDAATNXYFSAAjfHhNDxAvX1l-Q3wg5PxQ-HDImLiEpNTkLngeAHM8ll1SJRJwDmQ6ZIUiHIAKLnEykqNYUmQePgERMQkY4n4ONTMrO0dXAEo5T2aAdz4iAAtkMY3+9gA6APwj2ROvImxJYPYqmsRqCp3l5BvhEAp4Ow5IplGpJhIHjCUABqTB9DgPeqJFLaYGfLDfCp-CIAoEFEFeOjgyHQ2BKVTNVb4RF05TIAC0yFsGWy8Fu6MeWMaB1x5K8FVIGAUglUwK8iEuFFOyHY+GVLngFD5Bx0Xk0oH13V6myhplZEm1x3JbE4KAA2vD8DFkuAsHFEFcALruAgbB4KAkEYajPlDEY5GKLfhCURTHUnKkQqFjYEAHgAfHLkGb6WpZI6WfTDRSvKnMgpEIgBhxTIJwEQANZSWRjI5SdPIF1u8RXMayZ7lSphEnRWLxbFNagAVmomhF6fZqYA9OXKxxM2KQWWK1WoTW643m63pB2u+7e-3SkEQsPamOGik1FO55p08jl6vdxuKcvv8h4yAmhAA)

Redux์—์„œ Reducer์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ

Reducer funciton์„ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด [redux](https://github.com/reduxjs/redux)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, return type์„ ์ฒ˜๋ฆฌํ•˜๋Š” `Reducer` ํ˜•์‹์˜ ํŽธ๋ฆฌํ•œ helper๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„์˜ reducer example์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐ”๋€” ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. :

```tsx
import { Reducer } from 'redux';

export function reducer: Reducer() {}
```

#### useEffect / useLayoutEffect

`userEffect`์™€ `userLayoutEffect` ๋‘˜ ๋‹ค side effect๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๊ณ  ์„ ํƒ์ ์œผ๋กœ cleanup function์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋งŒ์•ฝ ์ด hook๋“ค์ด ๋ฐ˜ํ™˜ ๊ฐ’์„ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, type์ด ํ•„์š” ์—†๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. `useEffect`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ํ•จ์ˆ˜ ๋˜๋Š” `undefined` ์ด์™ธ์˜ ๋‹ค๋ฅธ ๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•˜์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด TypeScript์™€ React๋Š” ๋‹น์‹ ์—๊ฒŒ ๋น„๋ช…์„ ์ง€๋ฅผ๊ฒƒ์ž…๋‹ˆ๋‹ค. Arros functions๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ด ๋ฌธ์ œ๋Š” ๋‹ค์†Œ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. :

```ts
function DelayedEffect(props: { timerMs: number }) {
const { timerMs } = props;

useEffect(
() =>
setTimeout(() => {
/* do stuff */
}, timerMs),
[timerMs]
);
// ๋‚˜์œ ์˜ˆ์‹œ! setTimeout์€ ์•”๋ฌต์ ์œผ๋กœ ์ˆซ์ž๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
// arrow function์˜ body๊ฐ€ ์ค‘๊ด„ํ˜ธ๋กœ ๊ฐ์‹ธ์ง€์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
return null;
}
```

์œ„ ์˜ˆ์‹œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…

```tsx
function DelayedEffect(props: { timerMs: number }) {
const { timerMs } = props;

useEffect(() => {
setTimeout(() => {
/* do stuff */
}, timerMs);
}, [timerMs]);
// ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•; ํ™•์‹คํ•˜๊ฒŒ undefined๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ void keyword๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
return null;
}
```

#### useRef

TypeScript์—์„œ `useRef`๋Š” type argument๊ฐ€ ์ดˆ๊ธฐ ๊ฐ’์„ ์™„์ „ํžˆ ํฌํ•จ(cover)ํ•˜๋Š”์ง€ ์•„๋‹Œ์ง€์— ๋”ฐ๋ผ[read-only](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/abd69803c1b710db58d511f4544ec1b70bc9077c/types/react/v16/index.d.ts#L1025-L1039)๋˜๋Š” [mutable](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/abd69803c1b710db58d511f4544ec1b70bc9077c/types/react/v16/index.d.ts#L1012-L1023) ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์ž์˜ use case์— ๋งž๋Š” ๊ฒƒ์„ ์„ ํƒํ•˜์„ธ์š”.

##### Option 1: DOM element ref

**[DOM element์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”](https://reactjs.org/docs/refs-and-the-dom.html):** element type ๋งŒ์„ argument๋กœ ๋„˜๊ฒจ์ฃผ๊ณ  `null`์„ ์ดˆ๊ธฐ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ด ๊ฒฝ์šฐ์—, ๋ฐ˜ํ™˜๋˜๋Š” reference๋Š” React์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๋Š” read-only `.current`๋ฅผ ๊ฐ€์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. TypeScript๋Š” ์ด ref๋ฅผ element์˜ `ref` prop์œผ๋กœ ์ „๋‹ฌ ๋ฐ›๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค. :

```tsx
function Foo() {
// - ๊ฐ€๋Šฅํ•œ ์ƒ์„ธํ•˜๊ฒŒ ์ž‘์„ฑํ•˜์„ธ์š”. ์˜ˆ๋ฅผ๋“ค๋ฉด, HTMLDivElement๋Š” HTMLElement๋ณด๋‹ค ๋” ์ข‹๊ณ ,
// Element๋ณด๋‹ค๋Š” ํ›จ์‹  ๋” ์ข‹์€ ์„ ํƒ์ž…๋‹ˆ๋‹ค.
// - ๊ธฐ์ˆ ์ ์œผ๋กœ ๋งํ•˜์ž๋ฉด, ์ด๊ฒƒ์€ RefObject๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
const divRef = useRef(null);

useEffect(() => {
// ref.current๊ฐ€ null์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์ฃผ์˜ํ•˜์„ธ์š”.
// ์ด๊ฒƒ์€ ๋‹น์‹ ์ด ์กฐ๊ฑด์— ๋”ฐ๋ผ์„œ ref๋œ(ref-ed) element๋ฅผ renderํ•˜๊ฑฐ๋‚˜
// ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์„ ์žŠ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ๋Š” ํ˜„์ƒ์ž…๋‹ˆ๋‹ค.
if (!divRef.current) throw Error("divRef is not assigned");

// ์ด์ œ divRef.current๋Š” ํ™•์‹คํ•˜๊ฒŒ HTMLDivElement ์ž…๋‹ˆ๋‹ค.
doSomethingWith(divRef.current);
});

// React๊ฐ€ ๋‹น์‹ ์„ ์œ„ํ•ด ref๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜์žˆ๋„๋ก element์—๊ฒŒ ref๋ฅผ ์ „๋‹ฌํ•ด ์ฃผ์„ธ์š”.
return

etc
;
}
```

๋งŒ์•ฝ `divRef.current`๊ฐ€ ์ ˆ๋Œ€๋กœ null์ด ์•„๋‹๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์„ ํ™•์‹ ํ•œ๋‹ค๋ฉด, non-null assertion operator `!`์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. :

```tsx
const divRef = useRef(null!);
// ๋‚˜์ค‘์—... ์ด๊ฒƒ์ด null ์ธ์ง€ ํ™•์ธํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
doSomethingWith(divRef.current);
```

๋‹น์‹ ์ด type safety๊ฐ€ ๋ณด์žฅ๋œ๋‹ค๊ณ  ๋ฏธ๋ฆฌ ๊ฐ€์ •ํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ์— ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ Œ๋”๋ง ๊ณผ์ •์—์„œ ref๋ฅผ element์— ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์„ ์žŠ๊ฑฐ๋‚˜, ref๋œ(ref-ed) element๊ฐ€ ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง ๋œ๋‹ค๋ฉด runtime error๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Tip: ์–ด๋–ค HTMLElement๋ฅผ ์‚ฌ์šฉํ• ์ง€ ์„ ํƒํ•˜๊ธฐ

Ref๋Š” ๋ช…์‹œ์„ฑ(specificity)์„ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, `HTMLElement` ๋งŒ์„ ๋ช…์‹œํ•˜๋Š” ๊ฒƒ์€ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š๋‹ค๋Š” ๋ง์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋‹น์‹ ์ด ํ•„์š”ํ•œ element type์˜ ์ด๋ฆ„์„ ๋ชจ๋ฅธ๋‹ค๋ฉด, [lib.dom.ts](https://github.com/microsoft/TypeScript/blob/v3.9.5/lib/lib.dom.d.ts#L19224-L19343)์—์„œ ํ™•์ธํ•˜๊ฑฐ๋‚˜ ์˜๋„์ ์œผ๋กœ type error๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ณ  language service๊ฐ€ type์˜ ์ด๋ฆ„์„ ์•Œ๋ ค์ฃผ๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

![image](https://user-images.githubusercontent.com/6764957/116914284-1c436380-ac7d-11eb-9150-f52c571c5f07.png)

##### Option 2: Mutable value ref

**[mutable value๋ฅผ ๊ฐ€์ง€๊ธฐ ์œ„ํ•ด์„œ๋Š”](https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables):** ์›ํ•˜๋Š” type์„ ์‚ฌ์šฉํ•˜๊ณ  ์ดˆ๊ธฐ ๊ฐ’์ด ์™„์ „ํžˆ ํ•ด๋‹น type์— ์†ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

```tsx
function Foo() {
// ๊ธฐ์ˆ ์ ์œผ๋กœ ๋งํ•˜์ž๋ฉด, ์ด๊ฒƒ์€ MutableRefObject์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
const intervalRef = useRef(null);

// ๋‹น์‹ ์ด ์ง์ ‘ ref๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. (์ด๊ฒƒ์ด MutableRefObject๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ์ด์œ ์ด์ฃ .)
useEffect(() => {
intervalRef.current = setInterval(...);
return () => clearInterval(intervalRef.current);
}, []);

// ref๋Š” element์˜ "ref" prop์œผ๋กœ ์ „๋‹ฌ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
return Cancel timer;
}
```

##### ๋‹ค์Œ์˜ ์ž๋ฃŒ๋„ ํ™•์ธํ•ด ๋ณด์„ธ์š”.

- [@rajivpunjabi๊ฐ€ ์ž‘์„ฑํ•œ ๊ด€๋ จ ์ด์Šˆ](https://github.com/typescript-cheatsheets/react/issues/388) - [Playground](https://www.typescriptlang.org/play#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcARFDvmQNwCwAUI7hAHarwCCYYcAvHAAUASn4A+OAG9GjOHAD0CBLLnKGcxHABiwKBzgQwMYGxS4WUACbBWAczgwIcSxFwBXEFlYxkxtgDoVTQBJVmBjZAAbOAA3KLcsOAB3YEjogCNE1jc0-zgAGQBPG3tHOAAVQrAsAGVcKGAjOHTCuDdUErhWNgBabLSUVFQsWBNWA2qoX2hA9VU4AGFKXyx0AFk3H3TIxOwCOAB5dIArLHwgpHcoSm84MGJJmFbgdG74ZcsDVkjC2Y01f7yFQsdjvLAEACM-EwVBg-naWD2AB4ABLlNb5GpgZCsACiO083jEgn6kQAhMJ6HMQfpKJCFpE2IkBNg8HCEci0RisTj8VhCTBiaSKVSVIoAaoLnBQuFgFFYvFEikBpkujkMps4FgAB7VfCdLmY7F4gleOFwAByEHg7U63VYfXVg2Go1MhhG0ygf3mAHVUtF6jgYLtwUdTvguta4Bstjs9mGznCpVcbvB7u7YM90B8vj9vYgLkDqWxaeCAEzQ1n4eHDTnoo2801EknqykyObii5SmpnNifA5GMZmCzWOwOJwudwC3xjKUyiLROKRBLJf3NLJO9KanV64xj0koVifQ08k38s1Sv0DJZBxIx5DbRGhk6J5Nua5mu4PEZPOAvSNgsgnxsHmXZzIgRZyDSYIEAAzJWsI1k+BCovWp58gKcAAD5qmkQqtqKHbyCexoYRecw7IQugcAs76ptCdIQv4KZmoRcjyMRaGkU28A4aSKiUXAwwgpYtEfrcAh0mWzF0ax7bsZx3Lceetx8eqAlYPAMAABa6KJskSXAdKwTJ4kwGxCjyKy-bfK05SrDA8mWVagHAbZeScOY0CjqUE6uOgqDaRAOSfKqOYgb8KiMaZ9GSeCEIMkyMVyUwRHWYc7nSvAgUQEk6AjMQXpReWyWGdFLHeBZHEuTCQEZT8xVwaV8BxZCzUWZQMDvuMghBHASJVnCWhTLYApiH1chIqgxpGeCfCSIxAC+Yj3o+8YvvgSLyNNOLjeBGhTTNdLzVJy3reGMBbTtrB7RoB3XbNBAneCsHLatcbPhdV3GrdB1WYhw3IKNZq-W2DCLYRO7QPAljgsgORcDwVJAA)
- [Stefan Baumgartner์˜ ์˜ˆ์‹œ](https://fettblog.eu/typescript-react/hooks/#useref) - [Playground](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgIilQ3wFgAoCzAVwDsNgJa4AVJADxgElaxqYA6sBgALAGIQ01AM4AhfjCYAKAJRwA3hThwA9DrjBaw4CgA2waUjgB3YSLi1qp0wBo4AI35wYSZ6wCeYEgAymhQwGDw1lYoRHCmEBAA1oYA5nCY0HAozAASLACyADI8fDAAoqZIIEi0MFpwaEzS8IZllXAAvIjEMAB0MkjImAA8+cWl-JXVtTAAfEqOzioA3A1NtC1wTPIwirQAwuZoSV1wql1zGg3aenAt4RgOTqaNIkgn0g5ISAAmcDJvBA3h9TsBMAZeFNXjl-lIoEQ6nAOBZ+jddPpPPAmGgrPDEfAUS1pG5hAYvhAITBAlZxiUoRUqjU6m5RIDhOi7iIUF9RFYaqIIP9MlJpABCOCAUHJ0eDzm1oXAAGSKyHtUx9fGzNSacjaPWq6Ea6gI2Z9EUyVRrXV6gC+DRtVu0RBgxuYSnRIzm6O06h0ACpIdlfr9jExSQyOkxTP5GjkPFZBv9bKIDYSmbNpH04ABNFD+CV+nR2636kby+BETCddTlyo27w0zr4HycfC6L0lvUjLH7baHY5Jas7BRMI7AE42uYSUXed6pkY6HtMDulnQruCrCg2oA)

#### useImperativeHandle

ํ•ด๋‹น [Stackoverflow answer](https://stackoverflow.com/a/69292925/5415299)์— ๋”ฐ๋ฅด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.:

```tsx
// Countdown.tsx

// forwardRef๋กœ ์ „๋‹ฌ๋  handle type์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค
export type CountdownHandle = {
start: () => void;
};

type CountdownProps = {};

const Countdown = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
// start() ๋Š” ์—ฌ๊ธฐ์„œ ํƒ€์ž… ์ถ”๋ก (type inference) ๋ฉ๋‹ˆ๋‹ค
start() {
alert("Start");
},
}));

return

Countdown
;
});
```

```tsx
// ์ด ์ปดํฌ๋Š”ํŠธ๋Š” Countdown ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค

import Countdown, { CountdownHandle } from "./Countdown.tsx";

function App() {
const countdownEl = useRef(null);

useEffect(() => {
if (countdownEl.current) {
// start()๋Š” ์—ฌ๊ธฐ์„œ๋„ ํƒ€์ž… ์ถ”๋ก (type inference) ๋ฉ๋‹ˆ๋‹ค.
countdownEl.current.start();
}
}, []);

return ;
}
```

##### ๋‹ค์Œ์˜ ์ž๋ฃŒ๋„ ํ™•์ธํ•ด๋ณด์„ธ์š”:

- [ForwardRefRenderFunction ์‚ฌ์šฉํ•˜๊ธฐ](https://stackoverflow.com/a/62258685/5415299)

#### Custom Hooks

๋งŒ์•ฝ Custom Hook์—์„œ array๋ฅผ returnํ•œ๋‹ค๋ฉด, array์˜ ๊ฐ ์œ„์น˜์—์„œ ๊ฐ๊ธฐ ๋‹ค๋ฅธ type์„ ๊ฐ€์ง€๊ธฐ๋ฅผ ์›ํ•˜๊ฒ ์ง€๋งŒ TypeScript๋Š” union type์œผ๋กœ ์ถ”๋ก ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ํƒ€์ž… ์ถ”๋ก ์„ ํ”ผํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ [TS 3.4 const assertions](https://devblogs.microsoft.com/typescript/announcing-typescript-3-4/#const-assertions)์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

```tsx
import { useState } from "react";

export function useLoading() {
const [isLoading, setState] = useState(false);
const load = (aPromise: Promise) => {
setState(true);
return aPromise.finally(() => setState(false));
};
return [isLoading, load] as const; // (boolean | typeof load)[]์ด ์•„๋‹Œ [boolean, typeof load]์œผ๋กœ ์ถ”๋ก ํ•ฉ๋‹ˆ๋‹ค.
}
```

[TypeScript Playground์—์„œ ํ™•์ธํ•ด ๋ณด๊ธฐ](https://www.typescriptlang.org/play/?target=5&jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoCpAD0ljkwFcA7DYCZuRgZyQBkIKACbBmAcwAUASjgBvCnDhoO3eAG1g3AcNFiANHF4wAyjBQwkAXTgBeRMRgA6HklPmkEzCgA2vKQG4FJRV4b0EhWzgJFAAFHBBNJAAuODjcRIAeFGYATwA+GRs8uSDFIzcLCRgoRiQA0rgiGEYoTlj4xMdMUR9vHIlpW2Lys0qvXzr68kUAX0DpxqRm1rgNLXDdAzDhaxRuYOZVfzgAehO4UUwkKH21ACMICG9UZgMYHLAkCEw4baFrUSqVARb5RB5PF5wAA+cHen1BfykaksFBmQA)

์ด๋Ÿฐ ๋ฐฉ๋ฒ•์œผ๋กœ, destructureํ–ˆ์„ ๋•Œ destructuregํ•œ ์œ„์น˜์— ๋”ฐ๋ผ ์˜ฌ๋ฐ”๋ฅธ type์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋Œ€์•ˆ: tuple return type์„ ํ‘œ๋ช…ํ•˜๊ธฐ(assert)

๋งŒ์•ฝ [const assertions์ด ์‚ฌ์šฉํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋ฉด](https://github.com/babel/babel/issues/9800), ํ•จ์ˆ˜ return type์„ ํ‘œ๋ช…(assert)ํ•˜๊ฑฐ๋‚˜ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

```tsx
import { useState } from "react";

export function useLoading() {
const [isLoading, setState] = useState(false);
const load = (aPromise: Promise) => {
setState(true);
return aPromise.finally(() => setState(false));
};
return [isLoading, load] as [boolean, (aPromise: Promise) => Promise];
}
```

๋งŽ์€ custom hooks์„ ์ž‘์„ฑํ•œ๋‹ค๋ฉด, ์ž๋™์œผ๋กœ tuples์˜ ํƒ€์ž…์„ ๋ช…์‹œํ•ด์ฃผ๋Š” helper๋„ ํฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

```tsx
function tuplify(...elements: T) {
return elements;
}

function useArray() {
const numberValue = useRef(3).current;
const functionValue = useRef(() => {}).current;
return [numberValue, functionValue]; // type is (number | (() => void))[]
}

function useTuple() {
const numberValue = useRef(3).current;
const functionValue = useRef(() => {}).current;
return tuplify(numberValue, functionValue); // type is [number, () => void]
}
```

ํ•˜์ง€๋งŒ React team์€ ๋‘๊ฐœ ์ด์ƒ์˜ ๊ฐ’์„ returnํ•˜๋Š” custom hook์€ tuple ๋Œ€์‹  ์ ์ ˆํ•œ object๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค๋Š” ๊ฒƒ์— ์ฃผ์˜ํ•˜์„ธ์š”.

#### ๋” ๋งŽ์€ Hooks + TypeScript ์— ๊ด€ํ•œ ์ฝ์„ ๊ฑฐ๋ฆฌ:

- https://medium.com/@jrwebdev/react-hooks-in-typescript-88fce7001d0d
- https://fettblog.eu/typescript-react/hooks/#useref

๋งŒ์•ฝ React Hooks library๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ์‚ฌ์šฉ์ž๋“ค์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก types๋ฅผ export ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”.

#### React Hooks + TypeScript Libraries ์˜ˆ์‹œ:

- https://github.com/mweststrate/use-st8
- https://github.com/palmerhq/the-platform
- https://github.com/sw-yx/hooks

[์ถ”๊ฐ€ํ•  ๋‚ด์šฉ์ด ์žˆ๋‚˜์š”? issue๋ฅผ ์žฅ์„ฑํ•˜์„ธ์š”!](https://github.com/typescript-cheatsheets/react/issues/new).

#### Class Components

TypeScript์—์„œ `React.Component`๋Š” generic type (aka `React.Component`)์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ `React.Component`์— prop๊ณผ state type parameter๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. :

```tsx
type MyProps = {
// `interface`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค
message: string;
};
type MyState = {
count: number; // ์ด๋Ÿฐ ์‹์œผ๋กœ
};
class App extends React.Component {
state: MyState = {
// ๋” ๋‚˜์€ ํƒ€์ž… ์ถ”๋ก ์„ ์œ„ํ•ด ์„ ํƒ์ ์œผ๋กœ ์ž‘์„ฑํ•œ ๋‘ ๋ฒˆ์งธ annotation
count: 0,
};
render() {
return (


{this.props.message} {this.state.count}

);
}
}
```

[TypeScript Playground ํ™•์ธํ•ด ๋ณด๊ธฐ](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoCmATzCTgFlqAFHMAZzgF44BvCuHAD0QuAFd2wAHYBzOAANpMJFEzok8uME4oANuwhwIAawFwQSduxQykALjjsYUaTIDcFAL4fyNOo2oAZRgUZW4+MzQIMSkYBykxEAAjFTdhUV1gY3oYAAttLx80XRQrOABBMDA4JAAPZSkAE05kdBgAOgBhXEgpJFiAHiZWCA4AGgDg0KQAPgjyQSdphyYpsJ5+BcF0ozAYYAgpPUckKKa4FCkpCBD9w7hMaDgUmGUoOD96aUwVfrQkMyCKIxOJwAAMZm8ZiITRUAAoAJTzbZwIgwMRQKRwOGA7YDRrAABuM1xKN4eW07TAbHY7QsVhsSE8fAptKWynawNinlJcAGQgJxNxCJ8gh55E8QA)

์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ด๋Ÿฌํ•œ types/interfaces๋ฅผ export/import/extend ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”.

์™œ state๋ฅผ ๋‘ ๋ฒˆ annotate ํ• ๊นŒ์š”?

๋ฐ˜๋“œ์‹œ `state` class property์— annotateํ•  ํ•„์š”๋Š” ์—†์ง€๋งŒ, ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด `this.state`์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ state๋ฅผ ์ดˆ๊ธฐํ™” ํ•  ๋•Œ ๋” ๋‚˜์€ ํƒ€์ž… ์ถ”๋ก ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ์ด์œ ๋Š” ๋‘ ๊ฐœ์˜ annotation์€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ generic type parameter๋Š” `this.setState()`๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ด ๋ฉ”์†Œ๋“œ๋Š” base class์—์„œ ์˜ค๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ `state`๋ฅผ ์ดˆ๊ธฐํ™” ํ•˜๋Š” ๊ฒƒ์€ base implementation์„ overrideํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์‚ฌ์‹ค์ƒ ๋‹ค๋ฅธ ์ž‘์—…์„ ํ•˜๊ณ  ์žˆ์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. (=์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์‚ฌ์‹ค์ƒ ๊ฐ™์€ ์ž‘์—…์„ ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.)

[์—ฌ๊ธฐ์„œ @ferdaber์˜ ์˜๊ฒฌ์„ ํ™•์ธํ•ด๋ณด์„ธ์š”](https://github.com/typescript-cheatsheets/react/issues/57).

readonly๋Š” ํ•„์š” ์—†๋‹ค

์ข…์ข… ์ƒ˜ํ”Œ ์ฝ”๋“œ์— props์™€ state๊ฐ€ ๋ณ€ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด `readonly`๋ฅผ ํฌํ•ฉํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

```tsx
type MyProps = {
readonly message: string;
};
type MyState = {
readonly count: number;
};
```

`React.Component

`๊ฐ€ ์ด๋ฏธ props์™€ state๊ฐ€ ๋ณ€ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ํ‘œ์‹œํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ถ”๊ฐ€์ ์œผ๋กœ readonlyํ‘œ์‹œ๋ฅผ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ([PR ๊ณผ discussion์„ ํ™•์ธํ•˜์„ธ์š”!](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/26813))

**Class Methods**: ์›๋ž˜ ํ•˜๋˜๋ฐ๋กœ ํ•˜๋˜, ๋‹น์‹ ์˜ ํ•จ์ˆ˜๋ฅผ ์œ„ํ•œ ๋ชจ๋“  arguments๋Š” type์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ๋งŒ ๊ธฐ์–ตํ•˜์„ธ์š”.

```tsx
class App extends React.Component<{ message: string }, { count: number }> {
state = { count: 0 };
render() {
return (

this.increment(1)}>
{this.props.message} {this.state.count}

);
}
increment = (amt: number) => {
// ์ด๋Ÿฐ ์‹์œผ๋กœ
this.setState((state) => ({
count: state.count + amt,
}));
};
}
```

[TypeScript Playground์—์„œ ํ™•์ธํ•ด ๋ณด๊ธฐ](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoCtAGxQGc64BBMMOJADxiQDsATRsnQwAdAGFckHrxgAeAN5wQSBigDmSAFxw6MKMB5q4AXwA0cRWggBXHjG09rIAEZIoJgHwWKcHTBTccAC8FnBWtvZwAAwmANw+cET8bgAUAJTe5L6+RDDWUDxwKQnZcLJ8wABucBA8YtTAaADWQfLpwV4wABbAdCIGaETKdikAjGnGHiWlFt29ImA4YH3KqhrGsz19ugFIIuF2xtO+sgD0FZVTWdlp8ddH1wNDMsFFKCCRji5uGUFe8tNTqc4A0mkg4HM6NNISI6EgYABlfzcFI7QJ-IoA66lA6RNF7XFwADUcHeMGmxjStwSxjuxiAA)

**Class Properties**: ๋งŒ์•ฝ ๋‚˜์ค‘์— ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด class properties๋ฅผ ์„ ์–ธํ•œ๋‹ค๋ฉด, `state`์™€ ๊ฐ™์ด ์„ ์–ธํ•˜๋˜ ํ• ๋‹น์€ ํ•˜์ง€ ์•ˆ์Šต๋‹ˆ๋‹ค.

```tsx
class App extends React.Component<{
message: string;
}> {
pointer: number; // ์ด๋Ÿฐ ์‹์œผ๋กœ
componentDidMount() {
this.pointer = 3;
}
render() {
return (


{this.props.message} and {this.pointer}

);
}
}
```

[TypeScript Playground์—์„œ ํ™•์ธํ•ด ๋ณด๊ธฐ](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoCtAGxQGc64BBMMOJADxiQDsATRsnQwAdAGFckHrxgAeAN4U4cEEgYoA5kgBccOjCjAeGgNwUAvgD44i8sshHuUXTwCuIAEZIoJuAHo-OGpgAGskOBgAC2A6JTg0SQhpHhgAEWA+AFkIVxSACgBKGzjlKJiRBxTvOABeOABmMzs4cziifm9C4ublIhhXKB44PJLlOFk+YAA3S1GxmzK6CpwwJdV1LXM4FH4F6KXKp1aesdk-SZnRgqblY-MgA)

[์ถ”๊ฐ€ํ•  ๋‚ด์šฉ์ด ์žˆ๋‚˜์š”? issue๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”!](https://github.com/typescript-cheatsheets/react/issues/new).

#### getDerivedStateFromProps ํƒ€์ž…ํ•‘(Typing) ํ•˜๊ธฐ

`getDerivedStateFromProps`๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์—, [documentation](https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops)๊ณผ [You Probably Don't Need Derived State](https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html)๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. Derived State๋Š” memoization์„ ์„ค์ •ํ•œ๋Š” ๊ฒƒ์„ ๋„์šธ ์ˆ˜ ์žˆ๋Š” hooks์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ `getDerivedStateFromProps`๋ฅผ annotateํ•  ์ˆ˜ ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

1. ๋งŒ์•ฝ derived state์˜ type์„ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ–ˆ๊ณ , `getDerivedStateFromProps`์˜ return ๊ฐ’์ด ์„ค์ •ํ•œ type์„ ์ค€์ˆ˜ํ•˜๋Š”์ง€ ์•Œ๊ณ ์‹ถ์€ ๊ฒฝ์šฐ

```tsx
class Comp extends React.Component {
static getDerivedStateFromProps(props: Props, state: State): Partial | null {
//
}
}
```

2. ํ•จ์ˆ˜์˜ return ๊ฐ’์ด state๋ฅผ ๊ฒฐ์ •ํ•˜๋„๋ก ํ•˜๊ณ ์‹ถ์€ ๊ฒฝ์šฐ

```tsx
class Comp extends React.Component> {
static getDerivedStateFromProps(props: Props) {}
}
```

3. ๋‹ค๋ฅธ state fields์™€ derived state ๊ทธ๋ฆฌ๊ณ  memoization์„ ์›ํ•  ๊ฒฝ์šฐ

```tsx
type CustomValue = any;
interface Props {
propA: CustomValue;
}
interface DefinedState {
otherStateField: string;
}
type State = DefinedState & ReturnType;
function transformPropsToState(props: Props) {
return {
savedPropA: props.propA, // save for memoization
derivedState: props.propA,
};
}
class Comp extends React.PureComponent {
constructor(props: Props) {
super(props);
this.state = {
otherStateField: "123",
...transformPropsToState(props),
};
}
static getDerivedStateFromProps(props: Props, state: State) {
if (isEqual(props.propA, state.savedPropA)) return null;
return transformPropsToState(props);
}
}
```

[TypeScript Playground์—์„œ ํ™•์ธํ•ด ๋ณด๊ธฐ](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoUSWOYAZwFEBHAVxQBs5tcD2IATFHQAWAOnpJWHMuQowAnmCRwAwizoxcANQ4tlAXjgoAdvIDcFYMZhIomdMoAKOMHTgBvCnDhgXAQQAuVXVNEB12PQtyAF9La1t7NGUAESRMKyR+AGUYFBsPLzgIGGFbHLykADFgJHZ+II0oKwBzKNjyBSU4cvzDVPTjTJ7lADJEJBgWKGMAFUUkAB5OpAhMOBgoEzpMaBBnCFcZiGGAPijMFmMMYAhjdc3jbd39w+PcmwAKXwO6IJe6ACUBXI3iIk2mwO83joKAAbpkXoEfC46KJvmA-AAaOAAehxcBh8K40DgICQIAgwAAXnkbsZCt5+LZgPDsu8kEF0aj0X5CtE2hQ0OwhG4VLgwHAkAAPGzGfhuZDoGCiRxTJBi8C3JDWBb-bGnSFwNC3RosDDQL4ov4ooGeEFQugsJRQS0-AFRKHrYT0UQaCpwQx2z3eYqlKDDaq1epwABEAEYAEwAZhjmIZUNEmY2Wx2UD2KKOw1drgB6f5fMKfpgwDQcGaE1STVZEZw+Z+xd+cD1BPZQWGtvTwDWH3ozDY7A7aP82KrSF9cIR-gBQLBUzuxhY7HYHqhq4h2ceubbryLXPdFZiQA)

#### `defaultProps`๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์„์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค

[์ด ํŠธ์œ—](https://twitter.com/dan_abramov/status/1133878326358171650)์— ๋”ฐ๋ฅด๋ฉด, defaultProps๋Š” deprecate ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.. ๋‹ค์Œ์˜ ํ† ๋ก ์„ ํ™•์ธํ•ด ๋ณด์„ธ์š”.:

- [Original tweet](https://twitter.com/hswolff/status/1133759319571345408)
- [์ด article](https://medium.com/@matanbobi/react-defaultprops-is-dying-whos-the-contender-443c19d9e7f1)์—์„œ ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

object default value๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ†ต์ƒ์ ์œผ๋กœ ํ•ฉ์˜๋œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

Function Components:

```tsx
type GreetProps = { age?: number };

const Greet = ({ age = 21 }: GreetProps) => // etc
```

Class Components:

```tsx
type GreetProps = {
age?: number;
};

class Greet extends React.Component {
render() {
const { age = 21 } = this.props;
/*...*/
}
}

let el = ;
```

#### `defaultProps` ํƒ€์ดํ•‘ ํ•˜๊ธฐ

[TypeScript 3.0+](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html)์—์„œ ํƒ€์ž… ์ถ”๋ก ์˜ ์„ฑ๋Šฅ์ด ๋งค์šฐ ๋งŽ์ด ๋ฐœ์ „๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ [๋ช‡๋ช‡์˜ edge case ๋“ค์ด ๋ฌธ์ œ๊ฐ€ ๋˜๊ธฐ๋Š” ํ•ฉ๋‹ˆ๋‹ค.](https://github.com/typescript-cheatsheets/react/issues/61).

**Function Components**

```tsx
// ์‰ฌ์šด ๋ฐฉ๋ฒ•์œผ๋กœ typeof๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.; hoist๋˜๋Š” ๊ฒƒ์— ์ฃผ์˜ํ•˜์„ธ์š”!
// DefaultProps์„ ์„ ์–ธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
// e.g. https://github.com/typescript-cheatsheets/react/issues/415#issuecomment-841223219
type GreetProps = { age: number } & typeof defaultProps;

const defaultProps = {
age: 21,
};

const Greet = (props: GreetProps) => {
// etc
};
Greet.defaultProps = defaultProps;
```

_[TS Playground์—์„œ ํ™•์ธํ•ด๋ณด๊ธฐ](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcARFDvmQNwBQdMAnmFnAOKVYwAKxY6ALxwA3igDmWAFxwAdgFcQAIyxQ4AXzgAyOM1YQCcACZYCyeQBte-VPVwRZqeCbOXrEAXGEi6cCdLgAJgBGABo6dXo6e0d4TixuLzgACjAbGXjuPg9UAEovAD5RXzhKGHkoWTgAHiNgADcCkTScgDpkSTgAeiQFZVVELvVqrrrGiPpMmFaXcytsz2FZtwXbOiA)_

**Class components**์˜ ๊ฒฝ์šฐ, ํƒ€์ดํ•‘์„ ์œ„ํ•œ [๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•](https://github.com/typescript-cheatsheets/react/pull/103#issuecomment-481061483) (including using the `Pick` utility type)์ด ์žˆ์ง€๋งŒ, props definition์„ ๊ฑฐ๊พธ๋กœ ์ˆ˜ํ–‰("reverse") ํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

```tsx
type GreetProps = typeof Greet.defaultProps & {
age: number;
};

class Greet extends React.Component {
static defaultProps = {
age: 21,
};
/*...*/
}

// Type-checks! type assertion์ด ํ•„์š” ์—†์Œ!
let el = ;
```

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž‘์„ฑ์ž๋ฅผ ์œ„ํ•œJSX.LibraryManagedAttributes ๋‰˜์•™์Šค

์œ„์—์„œ ์†Œ๊ฐœ๋œ ๊ตฌํ˜„์€ ์•ฑ ๊ฐœ๋ฐœ์ž๋“ค์ด ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ์‚ฌ์šฉ(consume)ํ•  ์ˆ˜ ์žˆ๋„๋ก `GreetProps`๋ฅผ export ํ•˜๊ณ ์‹ถ์€ ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ `GreetProps`๊ฐ€ ์ •์˜๋˜๋Š” ๋ฐฉ๋ฒ•์ด ๋ฌธ์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. `age`๋Š” ๊ผญ ํ•„์š”ํ•˜์ง€ ์•Š์„ ๋•Œ์—๋„ `defaultProps`๋•Œ๋ฌธ์— ํ•„์ˆ˜์ ์ธ props๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

[`GreetProps`๋Š” ๋‹น์‹ ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์œ„ํ•œ _๋‚ด๋ถ€์ ์ธ_ ๊ทœ์น™(์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ)์ด์ง€, _์™ธ๋ถ€์ ์ธ_ ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค](https://github.com/typescript-cheatsheets/react/issues/66#issuecomment-453878710). ๋”ฐ๋ผ์„œ export๋ฅผ ์œ„ํ•œ type์„ ๋”ฐ๋กœ ๋งŒ๋“ค ๊ฑฐ๋‚˜, `JSX.LibraryManagedAttributes` utility๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

```tsx
// internal contract(๋‚ด๋ถ€์ ์ธ ๊ทœ์น™), export ๋˜์–ด์„œ๋Š” ์•ˆ๋œ๋‹ค
type GreetProps = {
age: number;
};

class Greet extends Component {
static defaultProps = { age: 21 };
}

// external contract(์™ธ๋ถ€์ ์ธ ๊ทœ์น™)
export type ApparentGreetProps = JSX.LibraryManagedAttributes;
```

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ์ž˜ ์‹คํ–‰๋˜์ง€๋งŒ, `ApparentGreetProps`๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ๋‹ค์†Œ ๋ฒˆ๊ฑฐ๋กœ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์—์„œ ์„ค๋ช…ํ•˜๋Š” `ComponentProps` utility๋กœ boilerplate๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

#### defaultProps๊ฐ€ ์žˆ๋Š” Component์˜ props๋ฅผ ์‚ฌ์šฉ(consume)ํ•˜๊ธฐ

`defaultProps`๊ฐ€ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” ์‹ค์ œ๋กœ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์ง€๋งŒ ํ•„์ˆ˜์ ์ธ props๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

##### Problem Statement

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ํ•˜๊ณ ์‹ถ๋‹ค๋ฉด,

```tsx
interface IProps {
name: string;
}
const defaultProps = {
age: 25,
};
const GreetComponent = ({ name, age }: IProps & typeof defaultProps) => (

{`Hello, my name is ${name}, ${age}`}

);
GreetComponent.defaultProps = defaultProps;

const TestComponent = (props: React.ComponentProps) => {
return

;
};

// 'age' property๋Š” '{ name: string; }'์— ์—†์ง€๋งŒ, '{ age: number; } type์—์„œ๋Š” ํ•„์ˆ˜์ ์ธ property ์ž…๋‹ˆ๋‹ค.
const el = ;
```

##### Solution

`JSX.LibraryManagedAttributes`๋ฅผ ์ ์šฉํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

```tsx
type ComponentProps = T extends React.ComponentType | React.Component
? JSX.LibraryManagedAttributes
: never;

const TestComponent = (props: ComponentProps) => {
return

;
};

// No error
const el = ;
```

[_TS Playground์—์„œ ํ™•์ธํ•ด ๋ณด๊ธฐ_](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcARFDvmQNwBQdMAnmFnAMImQB2W3MABWJhUAHgAqAPjgBeOOLhYAHjD4ATdNjwwAdJ3ARe-cSyyjg3AlihwB0gD6Yqu-Tz4xzl67cl04cAH44ACkAZQANHQAZYAAjKGQoJgBZZG5kAHMsNQBBGBgoOIBXVTFxABofPzgALjheADdrejoLVSgCPDYASSEIETgAb2r0kCw61AKLDPoAXzpcQ0m4NSxOooAbQWF0OWH-TPG4ACYAVnK6WfpF7mWAcUosGFdDd1k4AApB+uQxysO4LM6r0dnAAGRwZisCAEFZrZCbbb9VAASlk0g+1VEamADUkgwABgAJLAbDYQSogJg-MZwYDoAAkg1GWFmlSZh1mBNmogA9Di8XQUfQHlgni8jLpVustn0BnJpQjZTsWrzeXANsh2gwbstxFhJhK3nIPmAdnUjfw5WIoVgYXBReKuK9+JI0TJpPs4JQYEUoNw4KIABYARjgvN8VwYargADkIIooMQoAslvBSe8JAbns7JTSsDIyAQIBAyOHJDQgA)

#### ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ† ๋ก ๊ณผ ์ง€์‹

React.FC๋Š” ์™œ defaultProps์ด ๋™์ž‘ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋งŒ๋“ค๊นŒ์š”?

๋‹ค์Œ์˜ ํ† ๋ก ์„ ํ™•์ธํ•ด ๋ณด์„ธ์š”.:

- https://medium.com/@martin_hotell/10-typescript-pro-tips-patterns-with-or-without-react-5799488d6680
- https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30695
- https://github.com/typescript-cheatsheets/react/issues/87

์ด๊ฑด ํ˜„์žฌ ์ƒํƒœ์ผ ๋ฟ์ด๊ณ , ์ถ”ํ›„์—๋Š” ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜์ •๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

TypeScript 2.9 and earlier

TypeScript 2.9์™€ ๊ทธ ์ด์ „ ๋ฒ„์ „์—์„œ๋Š” ์ด๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋‹ค์–‘ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค์Œ ๋ฐฉ๋ฒ•์ด ์—ฌํƒœ๊นŒ์ง€ ํ™•์ธํ•œ ๋ฐฉ๋ฒ• ์ค‘ ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

```ts
type Props = Required & {
/* ์ถ”๊ฐ€์ ์ธ props */
};

export class MyComponent extends React.Component {
static defaultProps = {
foo: "foo",
};
}
```

์ด์ „์—๋Š” TypeScript์˜ `Partial type` ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ ์‚ฌํ•ญ์ด์—ˆ๋Š”๋ฐ, ์ด๋Š” ํ˜„์žฌ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋ž˜ํ•‘๋œ ์ธํ„ฐํŽ˜์ด์Šค์—์—์„œ ๋ถ€๋ถ„์ ์ธ ๋ฒ„์ „์„ ์ถฉ์กฑํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์œผ๋กœ type์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  defaultProps๋ฅผ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

```ts
interface IMyComponentProps {
firstProp?: string;
secondProp: IPerson[];
}

export class MyComponent extends React.Component {
public static defaultProps: Partial = {
firstProp: "default",
};
}
```

์ด ์ ‘๊ทผ ๋ฐฉ๋ฒ•์˜ ๋ฌธ์ œ์ ์€ `JSX.LibraryManagedAttributes`๋กœ ์ž‘๋™ํ•˜๋Š” ํƒ€์ž… ์ถ”๋ก ์— ๋ณต์žกํ•œ ์ด์Šˆ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋กœ JSX expression์„ ์ƒ์„ฑํ•  ๋•Œ ๋ชจ๋“  props๊ฐ€ ์„ ํƒ์‚ฌํ•ญ(optional)์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

[@ferdaber์˜ ์˜๊ฒฌ์„ ํ™•์ธํ•ด ๋ณด์„ธ์š”.](https://github.com/typescript-cheatsheets/react/issues/57) and [here](https://github.com/typescript-cheatsheets/react/issues/61).

[์ถ”๊ฐ€ํ•  ๋‚ด์šฉ์ด ์žˆ๋‚˜์š”? ์ด์Šˆ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”!](https://github.com/typescript-cheatsheets/react/issues/new).