42 |
43 |
44 |
45 |
46 |
47 |
48 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
49 |
50 |
51 |
52 |
53 |
54 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
55 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 shawn wang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/code-of-conduct.md:
--------------------------------------------------------------------------------
1 | # Our Code of Conduct
2 |
3 | This code of conduct outlines our expectations for participants within
4 | the [typescript-cheatsheets/react](https://github.com/typescript-cheatsheets/react) repository, as well as steps to
5 | reporting unacceptable behavior. We are committed to providing a welcoming and inspiring community for all and expect
6 | our code of conduct to be honored. Anyone who violates this code of conduct may be banned from the community.
7 |
8 | Our open source repository strives to:
9 |
10 | - **Be friendly and patient.**
11 | - **Be welcoming**: We strive to be a community that welcomes and supports people of all backgrounds and identities.
12 | This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration
13 | status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age,
14 | size, family status, political belief, religion, and mental and physical ability.
15 | - **Be considerate**: Your work will be used by other people, and you in turn will depend on the work of others. Any
16 | decision you take will affect users and colleagues, and you should take those consequences into account when making
17 | decisions. Remember that we're a world-wide community, so you might not be communicating in someone else's primary
18 | language.
19 | - **Be respectful**: Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor
20 | manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a
21 | personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a
22 | productive one.
23 | - **Be careful in the words that you choose**: we are a community of professionals, and we conduct ourselves
24 | professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary
25 | behavior aren't acceptable. This includes, but is not limited to:
26 | - Violent threats or language directed against another person.
27 | - Discriminatory jokes and language.
28 | - Posting sexually explicit or violent material.
29 | - Posting (or threatening to post) other people's personally identifying information ("doxing").
30 | - Personal insults, especially those using racist or sexist terms.
31 | - Unwelcome sexual attention.
32 | - Advocating for, or encouraging, any of the above behavior.
33 | - Repeated harassment of others. In general, if someone asks you to stop, then stop.
34 | - **When we disagree, try to understand why**: Disagreements, both social and technical, happen all the time. It is
35 | important that we resolve disagreements and differing views constructively. Remember that we’re different. The
36 | strength of our community comes from its diversity, people from a wide range of backgrounds. Different people have
37 | different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re
38 | wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping
39 | to resolve issues and learning from mistakes.
40 |
41 | This code is not exhaustive or complete. It serves to distill our common understanding of a collaborative, shared
42 | environment, and goals. We expect it to be followed in spirit as much as in the letter.
43 |
44 | ### Diversity Statement
45 |
46 | We encourage everyone to participate and are committed to building a repository for all. Although we may not be able to
47 | satisfy everyone, we all agree that everyone is equal. Whenever a participant has made a mistake, we expect them to take
48 | responsibility for it. If someone has been harmed or offended, it is our responsibility to listen carefully and
49 | respectfully, and do our best to right the wrong.
50 |
51 | Although this list cannot be exhaustive, we explicitly honor diversity in age, gender, gender identity or expression,
52 | culture, ethnicity, language, national origin, political beliefs, profession, race, religion, sexual orientation,
53 | socioeconomic status, and technical ability. We will not tolerate discrimination based on any of the protected
54 | characteristics above, including participants with disabilities.
55 |
56 | ### Reporting Issues
57 |
58 | If you experience or witness unacceptable behavior—or have any other concerns—please report it by contacting us (This
59 | repo is maintained by [@swyx](https://twitter.com/swyx), [@eps1lon](https://twitter.com/sebsilbermann)
60 | and [@filiptammergard](https://twitter.com/tammergard).). All reports will be handled with discretion. In your report
61 | please include:
62 |
63 | - Your contact information.
64 | - Names (real, nicknames, or pseudonyms) of any individuals involved. If there are additional witnesses, please include
65 | them as well. Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly
66 | available record (e.g. a mailing list archive or a public IRC logger), please include a link.
67 | - Any additional information that may be helpful.
68 |
69 | After filing a report, a representative will contact you personally. If the person who is harassing you is part of the
70 | response team, they will recuse themselves from handling your incident. A representative will then review the incident,
71 | follow up with any additional questions, and make a decision as to how to respond. We will respect confidentiality
72 | requests for the purpose of protecting victims of abuse.
73 |
74 | Anyone asked to stop unacceptable behavior is expected to comply immediately. If an individual engages in unacceptable
75 | behavior, the representative may take any action they deem appropriate, up to and including a permanent ban from our
76 | community without warning.
77 |
78 | ## Version
79 |
80 | This is version 1.0.0
81 |
82 | ## Thanks
83 |
84 | This code of conduct is based on the [Open Code of Conduct](https://github.com/todogroup/opencodeofconduct) from
85 | the [TODOGroup](http://todogroup.org).
86 |
87 | We are thankful for their work and all the communities who have paved the way with code of conducts.
88 |
--------------------------------------------------------------------------------
/copyFile.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const filesTopCopy = [
3 | {
4 | src: "../CONTRIBUTORS.md",
5 | dest: "src/pages/contributors.md",
6 | },
7 | {
8 | src: "../CONTRIBUTING.md",
9 | dest: "src/pages/contributing.md",
10 | },
11 | ];
12 |
13 | function copyFile(src, dest) {
14 | fs.copyFile(src, dest, (err) => {
15 | if (err) {
16 | console.log("Error Found:", err);
17 | } else {
18 | console.log("Files copied");
19 | }
20 | });
21 | }
22 |
23 | filesTopCopy.forEach(({ src, dest }) => {
24 | copyFile(src, dest);
25 | });
26 |
--------------------------------------------------------------------------------
/docs/advanced/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: intro
3 | sidebar_label: Intro
4 | title: Advanced Cheatsheet
5 | ---
6 |
7 | **This Advanced Cheatsheet** helps show and explain advanced usage of generic types for people writing reusable type utilities/functions/render prop/higher order components and TS+React **libraries**.
8 |
9 | - It also has miscellaneous tips and tricks for pro users.
10 | - Advice for contributing to DefinitelyTyped
11 | - The goal is to take _full advantage_ of TypeScript.
12 |
13 | **Creating React + TypeScript Libraries**
14 |
15 | The best tool for creating React + TS libraries right now is [`tsdx`](https://github.com/palmerhq/tsdx). Run `npx tsdx create` and select the "react" option. You can view [the React User Guide](https://github.com/palmerhq/tsdx/issues/5) for a few tips on React+TS library best practices and optimizations for production.
16 |
17 | Another option is [Rollpkg](https://github.com/rafgraph/rollpkg), which uses Rollup and the TypeScript compiler (not Babel) to create packages. It includes default configs for TypeScript, Prettier, ESLint, and Jest (setup for use with React), as well as Bundlephobia package stats for each build.
18 |
19 | - Be sure to also check [`basarat`'s guide](https://basarat.gitbooks.io/typescript/content/docs/quick/library.html) for library tsconfig settings.
20 | - Alec Larson: [The best Rollup config for TypeScript libraries](https://gist.github.com/aleclarson/9900ed2a9a3119d865286b218e14d226)
21 | - From the Angular world, check out https://github.com/bitjson/typescript-starter
22 |
--------------------------------------------------------------------------------
/docs/advanced/misc-concerns.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: misc_concerns
3 | title: "Section 3: Misc. Concerns"
4 | sidebar_label: Misc. Concerns
5 | ---
6 |
7 | Sometimes writing React isn't just about React. While we don't focus on other libraries like Redux (see below for more on that), here are some tips on other common concerns when making apps with React + TypeScript.
8 |
9 | ## Writing TypeScript Libraries instead of Apps
10 |
11 | `propTypes` may seem unnecessary with TypeScript, especially when building React + TypeScript **apps**, but they are still relevant when writing **libraries** which may be used by developers working in Javascript.
12 |
13 | ```ts
14 | interface MyComponentProps {
15 | autoHeight: boolean;
16 | secondProp: number;
17 | }
18 |
19 | export class MyComponent extends React.Component {
20 | static propTypes = {
21 | autoHeight: PropTypes.bool,
22 | secondProp: PropTypes.number.isRequired,
23 | };
24 | }
25 | ```
26 |
27 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
28 |
29 | ## Commenting Components
30 |
31 | TypeScript uses [TSDoc](https://github.com/Microsoft/tsdoc), a variant of JSDoc for TypeScript. This is very handy for writing component libraries and having useful descriptions pop up in autocomplete and other tooling (like the [Docz PropsTable](https://www.docz.site/docs/components-api#propstable)). The main thing to remember is to use `/** YOUR_COMMENT_HERE */` syntax in the line just above whatever you're annotating.
32 |
33 | ```tsx
34 | interface MyComponentProps {
35 | /** Description of prop "label".
36 | * @default foobar
37 | * */
38 | label?: string;
39 | }
40 |
41 | /**
42 | * General component description in JSDoc format. Markdown is *supported*.
43 | */
44 | export default function MyComponent({ label = "foobar" }: MyComponentProps) {
45 | return
Hello world {label}
;
46 | }
47 | ```
48 |
49 | [View in the TypeScript Playground](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoC4AOxiSk3STgFkBPABRzAGc4BvCnDgB6AFRi4AESQ80UYGBjAI1OBExww3OACIANigBGSfboB0Q4ZIACAEySMArvqwQIRlFCtxJYkVaGJvoA-ABccDwwCtQA5gDcFAC+FBTiYkKSAOJI1PQo+nBouJB5tHAOcgpKKmo0cABSAMpSEGhwmNAgKDDmrF4A1nYQAO51fGI8TmCQsEh2YpbkvgHkSAAes-AOzq4dTtQYtaxsAMIlqrkwABT8cEGmcAC8ep0eXrpwSRHsXBC8AEoBFYiDAnFA1AAeOzAABuAD4ABKmfQQOAjaD6OwCB76JKQkQwhGJchJIA)
50 |
51 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
52 |
53 | ## Namespaced Components
54 |
55 | Often when creating similar components or components that have a parent-child relationship, it is useful to namespace your components. Types can easily be added be using `Object.assign()`;
56 |
57 | ```tsx
58 | import { forwardRef } from "react";
59 |
60 | const Input = (props: any) => ;
61 |
62 | const Form = forwardRef(
63 | ({ children, ...otherProps }, ref) => (
64 |
67 | )
68 | );
69 |
70 | /**
71 | * Exported components now can be used as ``
72 | */
73 | export default Object.assign(Form, { Input: Input });
74 | ```
75 |
76 | [View in the TypeScript Playground](https://www.typescriptlang.org/play/?jsx=2&ssl=1&ssc=1&pln=14&pc=52#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoCtCAOwGd4BJGsAV3gF44AKMHMOgC44KGgE8AlHA4A+OAB5gLdnADeAOk18IAgL5wA9DIpVaDOADFoeLsnQx1maAHcUUACbJM8gBIAVAFkAGQARYAA3AFEAGyQQJBoYABoRcRlublU0AAtgaPciGhTNdQgYbKQoAAV+Ol0UokwpWR4KOAUnKDwNTTKK6tr9Ro5VRt1jcnb2rNz8wt02hQNOkAmJCQBuE3IDACpdtt24SIAPSFgkdzhqcFoEmDo4Gghna9E4ACMkOFY6S5FHgADeRWLoyQGpK7A0EgdTMNgwcGHAwUJBnaDwdxITAoVjReAAeQ+ACskBh1Cg6HRgABzGjcGEpVTw9jCFkwXSbIA)
77 |
78 | (Contributed by @bryceosterhaus, see [further discussion](https://github.com/typescript-cheatsheets/react/issues/165))
79 |
80 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
81 |
82 | ## Design System Development
83 |
84 | I do like [Docz](https://docz.site/) which takes basically [1 line of config](https://www.docz.site/documentation/project-configuration#typescript) to accept TypeScript. However it is newer and has a few more rough edges (many breaking changes since it is still < v1.0)
85 |
86 | For developing with Storybook, read the docs I wrote over here: . This includes automatic proptype documentation generation, which is awesome :)
87 |
88 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
89 |
90 | ## Migrating From Flow
91 |
92 | You should check out large projects that are migrating from flow to pick up concerns and tips:
93 |
94 | - [Jest](https://github.com/facebook/jest/pull/7554)
95 | - [Expo](https://github.com/expo/expo/issues/2164)
96 | - [React-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd/issues/982)
97 | - [Storybook](https://github.com/storybooks/storybook/issues/5030)
98 | - [VueJS](https://medium.com/the-vue-point/plans-for-the-next-iteration-of-vue-js-777ffea6fabf)
99 |
100 | Useful libraries:
101 |
102 | -
103 | -
104 | -
105 |
106 | If you have specific advice in this area, please file a PR!
107 |
108 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
109 |
110 | ## Prettier
111 |
112 | There isn't any real secret to Prettier for TypeScript. But its a great idea to run prettier on every commit!
113 |
114 | ```bash
115 | $ yarn add -D prettier husky lint-staged
116 | ```
117 |
118 | ```json
119 | // inside package.json
120 | {
121 | //...
122 | "husky": {
123 | "hooks": {
124 | "pre-commit": "lint-staged"
125 | }
126 | },
127 | "lint-staged": {
128 | "linters": {
129 | "src/*.{ts,tsx,js,jsx,css,scss,md}": [
130 | "prettier --trailing-comma es5 --single-quote --write",
131 | "git add"
132 | ],
133 | "ignore": ["**/dist/*, **/node_modules/*"]
134 | }
135 | },
136 | "prettier": {
137 | "printWidth": 80,
138 | "semi": false,
139 | "singleQuote": true,
140 | "trailingComma": "es5"
141 | }
142 | }
143 | ```
144 |
145 | Integrating this with ESlint may be a problem. We haven't written much on this yet, please contribute if you have a strong opinion. [Here's a helpful gist.](https://gist.github.com/JirkaVebr/519c7597517e4ba756d5b89e7cb4cc0e)
146 |
147 | For library authors, this is set up for you in [tsdx](https://github.com/palmerhq/tsdx/pull/45/files). You may also wish to check out the newer https://ts-engine.dev/ project.
148 |
149 | ## Testing
150 |
151 | Yes, you can test your types! You shouldn't use it for EVERYTHING, but it can help prevent regressions:
152 |
153 | - https://github.com/azz/jest-runner-tsc
154 | - https://github.com/SamVerschueren/tsd
155 | - https://github.com/ikatyang/dts-jest ([Demo](https://codesandbox.io/s/dts-test-frozen-public-demo-iyorn))
156 | - https://github.com/microsoft/dtslint ([Intro to dtslint](https://www.youtube.com/watch?v=nygcFEwOG8w&feature=share))
157 |
158 | ## Working with Non-TypeScript Libraries (writing your own index.d.ts)
159 |
160 | Lets say you want to use `de-indent`, but it isn't typed or on DefinitelyTyped. You get an error like this:
161 |
162 | ```
163 | [ts]
164 | Could not find a declaration file for module 'de-indent'. '/Users/swyx/Work/react-sfc-loader/node_modules/de-indent/index.js' implicitly has an 'any' type.
165 | Try `npm install @types/de-indent` if it exists or add a new declaration (.d.ts) file containing `declare module 'de-indent';` [7016]
166 | ```
167 |
168 | So create a `.d.ts` file anywhere in your project with the module definition:
169 |
170 | ```ts
171 | // de-indent.d.ts
172 | declare module "de-indent" {
173 | function deindent(): void;
174 | export = deindent; // default export
175 | }
176 | ```
177 |
178 |
179 |
180 | Further Discussion
181 |
182 | Any other tips? Please contribute on this topic! [We have an ongoing issue here with some references](https://github.com/typescript-cheatsheets/react/issues/8). We have more discussion and examples [in our issue here](https://github.com/typescript-cheatsheets/react/issues/12).
183 |
184 |
185 |
186 | ## Compilation Speed
187 |
188 | Compiling large TS projects can get slow. Here are some tips:
189 |
190 | - We have a dedicated repo tracking TS speed recommendations: https://github.com/typescript-cheatsheets/speed
191 | - Use [TS 3.0 Project references](https://react-typescript-cheatsheet.netlify.app/docs/advanced/patterns_by_version#typescript-30)
192 | - Check the official [TS performance wiki guidelines](https://github.com/microsoft/TypeScript/wiki/Performance) - note that [Dan Rossenwasser says to take it with a grain of salt](https://news.ycombinator.com/item?id=25199070)
193 | - Webpack ([see CRA diff](https://gist.github.com/jaredpalmer/d3016701589f14df8a3572df91a5754b)):
194 | - set `output.pathinfo = false`
195 | - set `optimization.splitChunks`, `optimization.removeAvailableModules`, `optimization.removeEmptyChunks` to `false`
196 |
--------------------------------------------------------------------------------
/docs/advanced/types-react-ap.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: types_react_api
3 | title: "Section 4: @types/react and @types/react-dom APIs"
4 | sidebar_label: "@types/react and @types/react-dom APIs"
5 | ---
6 |
7 | The `@types` typings export both "public" types meant for your use as well as "private" types that are for internal use.
8 |
9 | Check [SaltyCrane's React TypeScript Cheatsheet](https://github.com/saltycrane/typescript-cheatsheet) for a nice autogenerated complete reference.
10 |
11 | ## `@types/react`
12 |
13 | [Link to `.d.ts`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts)
14 |
15 | **Namespace: React**
16 |
17 | Most Commonly Used Interfaces and Types
18 |
19 | - `ReactNode` - anything that is renderable _inside_ of JSX, this is NOT the same as what can be rendered by a component!
20 | - `Component` - base class of all class-based components
21 | - `PureComponent` - base class for all class-based optimized components
22 | - `FC`, `FunctionComponent` - a complete interface for function components, often used to type external components instead of typing your own
23 | - `CSSProperties` - used to type style objects
24 | - all events: used to type event handlers
25 | - all event handlers: used to type event handlers
26 | - all consts: `Children`, `Fragment`, ... are all public and reflect the React runtime namespace
27 |
28 | Not Commonly Used but Good to know
29 |
30 | - `Ref` - used to type `innerRef`
31 | - `ElementType` - used for higher order components or operations on components, e.g. [Polymorphic Components](https://react-typescript-cheatsheet.netlify.app/docs/advanced/patterns_by_usecase#polymorphic-components)
32 | - `ReactElement` - [can be used if you want to pass it to `cloneElement`](https://www.reddit.com/r/reactjs/comments/ia8sdi/any_other_typescript_users_constantly_confused/g1npahe/) aka it's pretty rarely used
33 | - `ComponentType` - used for higher order components where you don't specifically deal with the intrinsic components
34 | - `ReactPortal` - used if you specifically need to type a prop as a portal, otherwise it is part of `ReactNode`
35 | - `ComponentClass` - a complete interface for the produced constructor function of a class declaration that extends `Component`, often used to type external components instead of typing your own
36 | - `JSXElementConstructor` - anything that TypeScript considers to be a valid thing that can go into the opening tag of a JSX expression
37 | - `ComponentProps` - props of a component - most useful for [Wrapping/Mirroring a HTML Element](https://react-typescript-cheatsheet.netlify.app/docs/advanced/patterns_by_usecase#wrappingmirroring-a-html-element)
38 | - `ComponentPropsWithRef` - props of a component where if it is a class-based component it will replace the `ref` prop with its own instance type
39 | - `ComponentPropsWithoutRef` - props of a component without its `ref` prop
40 | - `HTMLProps` and `HTMLAttributes` - these are the most generic versions, for global attributes (see a list of [attributes marked as "global attribute" on MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes)). In general, prefer `React.ComponentProps`, `React.JSX.IntrinsicElements`, or [specialized HTMLAttributes interfaces](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/a2aa0406e7bf269eef01292fcb2b24dee89a7d2b/types/react/index.d.ts#L1914-L2625):
41 |
42 |
43 |
44 | List of specialized HTMLAttributes
45 |
46 |
47 | Note that there are about 50 of these, which means there are some HTML elements which are not covered.
48 |
49 | - `AnchorHTMLAttributes`
50 | - `AudioHTMLAttributes`
51 | - `AreaHTMLAttributes`
52 | - `BaseHTMLAttributes`
53 | - `BlockquoteHTMLAttributes`
54 | - `ButtonHTMLAttributes`
55 | - `CanvasHTMLAttributes`
56 | - `ColHTMLAttributes`
57 | - `ColgroupHTMLAttributes`
58 | - `DataHTMLAttributes`
59 | - `DetailsHTMLAttributes`
60 | - `DelHTMLAttributes`
61 | - `DialogHTMLAttributes`
62 | - `EmbedHTMLAttributes`
63 | - `FieldsetHTMLAttributes`
64 | - `FormHTMLAttributes`
65 | - `HtmlHTMLAttributes`
66 | - `IframeHTMLAttributes`
67 | - `ImgHTMLAttributes`
68 | - `InsHTMLAttributes`
69 | - `InputHTMLAttributes`
70 | - `KeygenHTMLAttributes`
71 | - `LabelHTMLAttributes`
72 | - `LiHTMLAttributes`
73 | - `LinkHTMLAttributes`
74 | - `MapHTMLAttributes`
75 | - `MenuHTMLAttributes`
76 | - `MediaHTMLAttributes`
77 | - `MetaHTMLAttributes`
78 | - `MeterHTMLAttributes`
79 | - `QuoteHTMLAttributes`
80 | - `ObjectHTMLAttributes`
81 | - `OlHTMLAttributes`
82 | - `OptgroupHTMLAttributes`
83 | - `OptionHTMLAttributes`
84 | - `OutputHTMLAttributes`
85 | - `ParamHTMLAttributes`
86 | - `ProgressHTMLAttributes`
87 | - `SlotHTMLAttributes`
88 | - `ScriptHTMLAttributes`
89 | - `SelectHTMLAttributes`
90 | - `SourceHTMLAttributes`
91 | - `StyleHTMLAttributes`
92 | - `TableHTMLAttributes`
93 | - `TextareaHTMLAttributes`
94 | - `TdHTMLAttributes`
95 | - `ThHTMLAttributes`
96 | - `TimeHTMLAttributes`
97 | - `TrackHTMLAttributes`
98 | - `VideoHTMLAttributes`
99 | - `WebViewHTMLAttributes`
100 |
101 |
102 |
103 | - all methods: `createElement`, `cloneElement`, ... are all public and reflect the React runtime API
104 |
105 | [@Ferdaber's note](https://github.com/typescript-cheatsheets/react/pull/69): I discourage the use of most `...Element` types because of how black-boxy `React.JSX.Element` is. You should almost always assume that anything produced by `React.createElement` is the base type `React.ReactElement`.
106 |
107 | **Namespace: JSX**
108 |
109 | - `Element` - the type of any JSX expression. You should ideally never need to see or use this, but you do because of [a limitation of TypeScript](https://github.com/microsoft/TypeScript/issues/21699).
110 | - `LibraryManagedAttributes` - It specifies other places where JSX elements can declare and initialize property types. Used to resolve static `defaultProps` and `propTypes` with the internal props type of a component.
111 | - `IntrinsicElements` - every possible built-in component that can be typed in as a lowercase tag name in JSX. If you're using this to get the attributes for a HTML element, `React.ComponentProps` may be more readable as it doesn't require knowing what "Intrinsic" means.
112 |
113 | Not commonly used but good to know
114 |
115 | - `IntrinsicAttributes` set of attributes that all `IntrinsicElements` support... basically just `key`.
116 | - `ElementChildrenAttribute` name of property that TS looks at to figure out what types of children a component supports. Basically the `children` property
117 | - `ElementAttributesProperty` name of property that TS looks at to figure out what attributes a component supports. Basically the `props` property (for a class instance)
118 |
119 | **Don't use/Internal/Deprecated**
120 |
121 | Anything not listed above is considered an internal type and not public. If you're not sure you can check out the source of `@types/react`. The types are annotated accordingly.
122 |
123 | - `SFCElement`
124 | - `SFC`
125 | - `ComponentState`
126 | - `LegacyRef`
127 | - `StatelessComponent`
128 | - `ReactType`
129 |
130 | ### Adding non-standard attributes
131 |
132 | The attributes allowed on host components such as `button` or `img` follow the
133 | [HTML living standard](https://html.spec.whatwg.org/). New features that are not yet part of the living standard
134 | or are only implemented by certain browsers will therefore cause a type error. If
135 | you specifically write code for these browsers or polyfill these attributes you can
136 | use [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation) to still get those components type checked without having
137 | to use `any` or `@ts-ignore`.
138 |
139 | In this example we'll add the [`loading`](https://www.chromestatus.com/feature/5645767347798016) attribute which adds support for [lazy-loading](https://web.dev/native-lazy-loading) images on Chrome:
140 |
141 | ```ts
142 | // react-unstable-attributes.d.ts
143 | import "react";
144 |
145 | declare module "react" {
146 | interface ImgHTMLAttributes extends HTMLAttributes {
147 | loading?: "auto" | "eager" | "lazy";
148 | }
149 | }
150 | ```
151 |
152 | ## `@types/react-dom`
153 |
154 | To be written
155 |
--------------------------------------------------------------------------------
/docs/advanced/utility-types.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: utility_types
3 | title: "Utility Types"
4 | sidebar_label: Utility Types
5 | ---
6 |
7 | We will assume knowledge of utility types covered in the sister project [`typescript-cheatsheets/utilities`](https://github.com/typescript-cheatsheets/utilities). Look up libraries included there as well for your typing needs.
8 |
9 | If you intend to maintain a large TS codebase/a nontrivial React+TS library, **we strongly recommend exploring these utilities** so that you don't reinvent the wheel and/or lose sanity trying to do so. Studying their code can also teach you a lot of advanced TS that is not covered here.
10 |
11 | I also recommend having a good working knowledge of how to construct the inbuilt utility types from scratch. See [Dr. Rauschmayer's guide](https://2ality.com/2020/06/computing-with-types.html) for a concise introduction.
12 |
13 | A level of comfort with **generic types** is therefore required. Here are some helpful resources:
14 |
15 | - https://ts.chibicode.com/generics/
16 |
--------------------------------------------------------------------------------
/docs/basic/editor-integration.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: editor_integration
3 | title: Editor Tooling and Integration
4 | ---
5 |
6 | - VSCode
7 | - swyx's VSCode Extension: https://github.com/sw-yx/swyx-react-typescript-snippets
8 | - amVim: https://marketplace.visualstudio.com/items?itemName=auiworks.amvim
9 | - VIM
10 | - https://github.com/Quramy/tsuquyomi
11 | - nvim-typescript?
12 | - https://github.com/leafgarland/typescript-vim
13 | - peitalin/vim-jsx-typescript
14 | - NeoVim: https://github.com/neoclide/coc.nvim
15 | - other discussion: https://mobile.twitter.com/ryanflorence/status/1085715595994095620
16 |
17 | You are free to use this repo's TSX logo if you wish:
18 |
19 | [](https://user-images.githubusercontent.com/6764957/53868378-2b51fc80-3fb3-11e9-9cee-0277efe8a927.png)
20 |
21 | You may also wish to use alternative logos - [jsx-tsx-logos](https://github.com/Protectator/jsx-tsx-logos)
22 |
23 | 
24 |
--------------------------------------------------------------------------------
/docs/basic/examples.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: examples
3 | title: Example App
4 | sidebar_label: Examples
5 | ---
6 |
7 | - [Create React App TypeScript Todo Example 2021](https://github.com/laststance/create-react-app-typescript-todo-example-2021)
8 | - [Ben Awad's 14 hour Fullstack React/GraphQL/TypeScript Tutorial](https://www.youtube.com/watch?v=I6ypD7qv3Z8)
9 | - [Cypress Realworld App](https://github.com/cypress-io/cypress-realworld-app)
10 |
--------------------------------------------------------------------------------
/docs/basic/getting-started/basic-type-examples.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: basic_type_example
3 | title: Typing Component Props
4 | ---
5 |
6 | This is intended as a basic orientation and reference for React developers familiarizing with TypeScript.
7 |
8 | ## Basic Prop Types Examples
9 |
10 | A list of TypeScript types you will likely use in a React+TypeScript app:
11 |
12 | ```tsx
13 | type AppProps = {
14 | message: string;
15 | count: number;
16 | disabled: boolean;
17 | /** array of a type! */
18 | names: string[];
19 | /** string literals to specify exact string values, with a union type to join them together */
20 | status: "waiting" | "success";
21 | /** an object with known properties (but could have more at runtime) */
22 | obj: {
23 | id: string;
24 | title: string;
25 | };
26 | /** array of objects! (common) */
27 | objArr: {
28 | id: string;
29 | title: string;
30 | }[];
31 | /** any non-primitive value - can't access any properties (NOT COMMON but useful as placeholder) */
32 | obj2: object;
33 | /** an interface with no required properties - (NOT COMMON, except for things like `React.Component<{}, State>`) */
34 | obj3: {};
35 | /** a dict object with any number of properties of the same type */
36 | dict1: {
37 | [key: string]: MyTypeHere;
38 | };
39 | dict2: Record; // equivalent to dict1
40 | /** function that doesn't take or return anything (VERY COMMON) */
41 | onClick: () => void;
42 | /** function with named prop (VERY COMMON) */
43 | onChange: (id: number) => void;
44 | /** function type syntax that takes an event (VERY COMMON) */
45 | onChange: (event: React.ChangeEvent) => void;
46 | /** alternative function type syntax that takes an event (VERY COMMON) */
47 | onClick(event: React.MouseEvent): void;
48 | /** any function as long as you don't invoke it (not recommended) */
49 | onSomething: Function;
50 | /** an optional prop (VERY COMMON!) */
51 | optional?: OptionalType;
52 | /** when passing down the state setter function returned by `useState` to a child component. `number` is an example, swap out with whatever the type of your state */
53 | setState: React.Dispatch>;
54 | };
55 | ```
56 |
57 | ### `object` as the non-primitive type
58 |
59 | `object` is a common source of misunderstanding in TypeScript. It does not mean "any object" but rather "any non-primitive type", which means it represents anything that is not `number`, `bigint`, `string`, `boolean`, `symbol`, `null` or `undefined`.
60 |
61 | Typing "any non-primitive value" is most likely not something that you should do much in React, which means you will probably not use `object` much.
62 |
63 | ### Empty interface, `{}` and `Object`
64 |
65 | An empty interface, `{}` and `Object` all represent "any non-nullish value"—not "an empty object" as you might think. [Using these types is a common source of misunderstanding and is not recommended](https://typescript-eslint.io/rules/no-empty-interface/).
66 |
67 | ```ts
68 | interface AnyNonNullishValue {} // equivalent to `type AnyNonNullishValue = {}` or `type AnyNonNullishValue = Object`
69 |
70 | let value: AnyNonNullishValue;
71 |
72 | // these are all fine, but might not be expected
73 | value = 1;
74 | value = "foo";
75 | value = () => alert("foo");
76 | value = {};
77 | value = { foo: "bar" };
78 |
79 | // these are errors
80 | value = undefined;
81 | value = null;
82 | ```
83 |
84 | ## Useful React Prop Type Examples
85 |
86 | Relevant for components that accept other React components as props.
87 |
88 | ```tsx
89 | export declare interface AppProps {
90 | children?: React.ReactNode; // best, accepts everything React can render
91 | childrenElement: React.JSX.Element; // A single React element
92 | style?: React.CSSProperties; // to pass through style props
93 | onChange?: React.FormEventHandler; // form events! the generic parameter is the type of event.target
94 | // more info: https://react-typescript-cheatsheet.netlify.app/docs/advanced/patterns_by_usecase/#wrappingmirroring
95 | props: Props & React.ComponentPropsWithoutRef<"button">; // to impersonate all the props of a button element and explicitly not forwarding its ref
96 | props2: Props & React.ComponentPropsWithRef; // to impersonate all the props of MyButtonForwardedRef and explicitly forwarding its ref
97 | }
98 | ```
99 |
100 |
101 | Small React.ReactNode edge case before React 18
102 |
103 | Before the [React 18 type updates](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56210), this code typechecked but had a runtime error:
104 |
105 | ```tsx
106 | type Props = {
107 | children?: React.ReactNode;
108 | };
109 |
110 | function Comp({ children }: Props) {
111 | return
{children}
;
112 | }
113 | function App() {
114 | // Before React 18: Runtime error "Objects are not valid as a React child"
115 | // After React 18: Typecheck error "Type '{}' is not assignable to type 'ReactNode'"
116 | return {{}};
117 | }
118 | ```
119 |
120 | This is because `ReactNode` includes `ReactFragment` which allowed type `{}` before React 18.
121 |
122 | [Thanks @pomle for raising this.](https://github.com/typescript-cheatsheets/react/issues/357)
123 |
124 |
125 |
126 |
127 | React.JSX.Element vs React.ReactNode?
128 |
129 | Quote [@ferdaber](https://github.com/typescript-cheatsheets/react/issues/57): A more technical explanation is that a valid React node is not the same thing as what is returned by `React.createElement`. Regardless of what a component ends up rendering, `React.createElement` always returns an object, which is the `React.JSX.Element` interface, but `React.ReactNode` is the set of all possible return values of a component.
130 |
131 | - `React.JSX.Element` -> Return value of `React.createElement`
132 | - `React.ReactNode` -> Return value of a component
133 |
134 |
135 |
136 | [More discussion: Where ReactNode does not overlap with React.JSX.Element](https://github.com/typescript-cheatsheets/react/issues/129)
137 |
138 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
139 |
140 | ## Types or Interfaces?
141 |
142 | You can use either Types or Interfaces to type Props and State, so naturally the question arises - which do you use?
143 |
144 | ### TL;DR
145 |
146 | Use Interface until You Need Type - [orta](https://twitter.com/orta/status/1356129195835973632?s=20).
147 |
148 | ### More Advice
149 |
150 | Here's a helpful rule of thumb:
151 |
152 | - always use `interface` for public API's definition when authoring a library or 3rd party ambient type definitions, as this allows a consumer to extend them via _declaration merging_ if some definitions are missing.
153 |
154 | - consider using `type` for your React Component Props and State, for consistency and because it is more constrained.
155 |
156 | You can read more about the reasoning behind this rule of thumb in [Interface vs Type alias in TypeScript 2.7](https://medium.com/@martin_hotell/interface-vs-type-alias-in-typescript-2-7-2a8f1777af4c).
157 |
158 | The TypeScript Handbook now also includes guidance on [Differences Between Type Aliases and Interfaces](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces).
159 |
160 | > Note: At scale, there are performance reasons to prefer interfaces ([see official Microsoft notes on this](https://github.com/microsoft/TypeScript/wiki/Performance#preferring-interfaces-over-intersections)) but [take this with a grain of salt](https://news.ycombinator.com/item?id=25201887)
161 |
162 | Types are useful for union types (e.g. `type MyType = TypeA | TypeB`) whereas Interfaces are better for declaring dictionary shapes and then `implementing` or `extending` them.
163 |
164 | ### Useful table for Types vs Interfaces
165 |
166 | It's a nuanced topic, don't get too hung up on it. Here's a handy table:
167 |
168 | | Aspect | Type | Interface |
169 | | ----------------------------------------------- | :--: | :-------: |
170 | | Can describe functions | ✅ | ✅ |
171 | | Can describe constructors | ✅ | ✅ |
172 | | Can describe tuples | ✅ | ✅ |
173 | | Interfaces can extend it | ⚠️ | ✅ |
174 | | Classes can extend it | 🚫 | ✅ |
175 | | Classes can implement it (`implements`) | ⚠️ | ✅ |
176 | | Can intersect another one of its kind | ✅ | ⚠️ |
177 | | Can create a union with another one of its kind | ✅ | 🚫 |
178 | | Can be used to create mapped types | ✅ | 🚫 |
179 | | Can be mapped over with mapped types | ✅ | ✅ |
180 | | Expands in error messages and logs | ✅ | 🚫 |
181 | | Can be augmented | 🚫 | ✅ |
182 | | Can be recursive | ⚠️ | ✅ |
183 |
184 | ⚠️ In some cases
185 |
186 | (source: [Karol Majewski](https://twitter.com/karoljmajewski/status/1082413696075382785))
187 |
188 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
189 |
--------------------------------------------------------------------------------
/docs/basic/getting-started/class-components.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: class_components
3 | title: Class Components
4 | ---
5 |
6 | Within TypeScript, `React.Component` is a generic type (aka `React.Component`), so you want to provide it with (optional) prop and state type parameters:
7 |
8 | ```tsx
9 | type MyProps = {
10 | // using `interface` is also ok
11 | message: string;
12 | };
13 | type MyState = {
14 | count: number; // like this
15 | };
16 | class App extends React.Component {
17 | state: MyState = {
18 | // optional second annotation for better type inference
19 | count: 0,
20 | };
21 | render() {
22 | return (
23 |
24 | {this.props.message} {this.state.count}
25 |
26 | );
27 | }
28 | }
29 | ```
30 |
31 | [View in the TypeScript Playground](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoCmATzCTgFlqAFHMAZzgF44BvCuHAD0QuAFd2wAHYBzOAANpMJFEzok8uME4oANuwhwIAawFwQSduxQykALjjsYUaTIDcFAL4fyNOo2oAZRgUZW4+MzQIMSkYBykxEAAjFTdhUV1gY3oYAAttLx80XRQrOABBMDA4JAAPZSkAE05kdBgAOgBhXEgpJFiAHiZWCA4AGgDg0KQAPgjyQSdphyYpsJ5+BcF0ozAYYAgpPUckKKa4FCkpCBD9w7hMaDgUmGUoOD96aUwVfrQkMyCKIxOJwAAMZm8ZiITRUAAoAJTzbZwIgwMRQKRwOGA7YDRrAABuM1xKN4eW07TAbHY7QsVhsSE8fAptKWynawNinlJcAGQgJxNxCJ8gh55E8QA)
32 |
33 | Don't forget that you can export/import/extend these types/interfaces for reuse.
34 |
35 |
36 | Why annotate state twice?
37 |
38 | It isn't strictly necessary to annotate the `state` class property, but it allows better type inference when accessing `this.state` and also initializing the state.
39 |
40 | This is because they work in two different ways, the 2nd generic type parameter will allow `this.setState()` to work correctly, because that method comes from the base class, but initializing `state` inside the component overrides the base implementation so you have to make sure that you tell the compiler that you're not actually doing anything different.
41 |
42 | [See commentary by @ferdaber here](https://github.com/typescript-cheatsheets/react/issues/57).
43 |
44 |
45 |
46 |
47 | No need for readonly
48 |
49 | You often see sample code include `readonly` to mark props and state immutable:
50 |
51 | ```tsx
52 | type MyProps = {
53 | readonly message: string;
54 | };
55 | type MyState = {
56 | readonly count: number;
57 | };
58 | ```
59 |
60 | This is not necessary as `React.Component
` already marks them as immutable. ([See PR and discussion!](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/26813))
61 |
62 |
63 |
64 | **Class Methods**: Do it like normal, but just remember any arguments for your functions also need to be typed:
65 |
66 | ```tsx
67 | class App extends React.Component<{ message: string }, { count: number }> {
68 | state = { count: 0 };
69 | render() {
70 | return (
71 |
74 | );
75 | }
76 | increment = (amt: number) => {
77 | // like this
78 | this.setState((state) => ({
79 | count: state.count + amt,
80 | }));
81 | };
82 | }
83 | ```
84 |
85 | [View in the TypeScript Playground](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoCtAGxQGc64BBMMOJADxiQDsATRsnQwAdAGFckHrxgAeAN5wQSBigDmSAFxw6MKMB5q4AXwA0cRWggBXHjG09rIAEZIoJgHwWKcHTBTccAC8FnBWtvZwAAwmANw+cET8bgAUAJTe5L6+RDDWUDxwKQnZcLJ8wABucBA8YtTAaADWQfLpwV4wABbAdCIGaETKdikAjGnGHiWlFt29ImA4YH3KqhrGsz19ugFIIuF2xtO+sgD0FZVTWdlp8ddH1wNDMsFFKCCRji5uGUFe8tNTqc4A0mkg4HM6NNISI6EgYABlfzcFI7QJ-IoA66lA6RNF7XFwADUcHeMGmxjStwSxjuxiAA)
86 |
87 | **Class Properties**: If you need to declare class properties for later use, just declare it like `state`, but without assignment:
88 |
89 | ```tsx
90 | class App extends React.Component<{
91 | message: string;
92 | }> {
93 | pointer: number; // like this
94 | componentDidMount() {
95 | this.pointer = 3;
96 | }
97 | render() {
98 | return (
99 |
100 | {this.props.message} and {this.pointer}
101 |
102 | );
103 | }
104 | }
105 | ```
106 |
107 | [View in the TypeScript Playground](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoCtAGxQGc64BBMMOJADxiQDsATRsnQwAdAGFckHrxgAeAN4U4cEEgYoA5kgBccOjCjAeGgNwUAvgD44i8sshHuUXTwCuIAEZIoJuAHo-OGpgAGskOBgAC2A6JTg0SQhpHhgAEWA+AFkIVxSACgBKGzjlKJiRBxTvOABeOABmMzs4cziifm9C4ublIhhXKB44PJLlOFk+YAA3S1GxmzK6CpwwJdV1LXM4FH4F6KXKp1aesdk-SZnRgqblY-MgA)
108 |
109 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
110 |
111 | ## Typing getDerivedStateFromProps
112 |
113 | Before you start using `getDerivedStateFromProps`, please go through the [documentation](https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops) and [You Probably Don't Need Derived State](https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html). Derived State can be implemented using hooks which can also help set up memoization.
114 |
115 | Here are a few ways in which you can annotate `getDerivedStateFromProps`
116 |
117 | 1. If you have explicitly typed your derived state and want to make sure that the return value from `getDerivedStateFromProps` conforms to it.
118 |
119 | ```tsx
120 | class Comp extends React.Component {
121 | static getDerivedStateFromProps(
122 | props: Props,
123 | state: State
124 | ): Partial | null {
125 | //
126 | }
127 | }
128 | ```
129 |
130 | 2. When you want the function's return value to determine your state.
131 |
132 | ```tsx
133 | class Comp extends React.Component<
134 | Props,
135 | ReturnType
136 | > {
137 | static getDerivedStateFromProps(props: Props) {}
138 | }
139 | ```
140 |
141 | 3. When you want derived state with other state fields and memoization
142 |
143 | ```tsx
144 | type CustomValue = any;
145 | interface Props {
146 | propA: CustomValue;
147 | }
148 | interface DefinedState {
149 | otherStateField: string;
150 | }
151 | type State = DefinedState & ReturnType;
152 | function transformPropsToState(props: Props) {
153 | return {
154 | savedPropA: props.propA, // save for memoization
155 | derivedState: props.propA,
156 | };
157 | }
158 | class Comp extends React.PureComponent {
159 | constructor(props: Props) {
160 | super(props);
161 | this.state = {
162 | otherStateField: "123",
163 | ...transformPropsToState(props),
164 | };
165 | }
166 | static getDerivedStateFromProps(props: Props, state: State) {
167 | if (isEqual(props.propA, state.savedPropA)) return null;
168 | return transformPropsToState(props);
169 | }
170 | }
171 | ```
172 |
173 | [View in the TypeScript Playground](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoUSWOYAZwFEBHAVxQBs5tcD2IATFHQAWAOnpJWHMuQowAnmCRwAwizoxcANQ4tlAXjgoAdvIDcFYMZhIomdMoAKOMHTgBvCnDhgXAQQAuVXVNEB12PQtyAF9La1t7NGUAESRMKyR+AGUYFBsPLzgIGGFbHLykADFgJHZ+II0oKwBzKNjyBSU4cvzDVPTjTJ7lADJEJBgWKGMAFUUkAB5OpAhMOBgoEzpMaBBnCFcZiGGAPijMFmMMYAhjdc3jbd39w+PcmwAKXwO6IJe6ACUBXI3iIk2mwO83joKAAbpkXoEfC46KJvmA-AAaOAAehxcBh8K40DgICQIAgwAAXnkbsZCt5+LZgPDsu8kEF0aj0X5CtE2hQ0OwhG4VLgwHAkAAPGzGfhuZDoGCiRxTJBi8C3JDWBb-bGnSFwNC3RosDDQL4ov4ooGeEFQugsJRQS0-AFRKHrYT0UQaCpwQx2z3eYqlKDDaq1epwABEAEYAEwAZhjmIZUNEmY2Wx2UD2KKOw1drgB6f5fMKfpgwDQcGaE1STVZEZw+Z+xd+cD1BPZQWGtvTwDWH3ozDY7A7aP82KrSF9cIR-gBQLBUzuxhY7HYHqhq4h2ceubbryLXPdFZiQA)
174 |
--------------------------------------------------------------------------------
/docs/basic/getting-started/concurrent.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: concurrent
3 | title: Concurrent React/React Suspense
4 | ---
5 |
6 | _Not written yet._ watch for more on React Suspense and Time Slicing.
7 |
8 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
9 |
--------------------------------------------------------------------------------
/docs/basic/getting-started/context.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: context
3 | title: Context
4 | ---
5 |
6 | ## Basic example
7 |
8 | Here's a basic example of creating a context containing the active theme.
9 |
10 | ```tsx
11 | import { createContext } from "react";
12 |
13 | type ThemeContextType = "light" | "dark";
14 |
15 | const ThemeContext = createContext("light");
16 | ```
17 |
18 | Wrap the components that need the context with a context provider:
19 |
20 | ```tsx
21 | import { useState } from "react";
22 |
23 | const App = () => {
24 | const [theme, setTheme] = useState("light");
25 |
26 | return (
27 |
28 |
29 |
30 | );
31 | };
32 | ```
33 |
34 | Call `useContext` to read and subscribe to the context.
35 |
36 | ```tsx
37 | import { useContext } from "react";
38 |
39 | const MyComponent = () => {
40 | const theme = useContext(ThemeContext);
41 |
42 | return
The current theme is {theme}.
;
43 | };
44 | ```
45 |
46 | ## Without default context value
47 |
48 | If you don't have any meaningful default value, specify `null`:
49 |
50 | ```tsx
51 | import { createContext } from "react";
52 |
53 | interface CurrentUserContextType {
54 | username: string;
55 | }
56 |
57 | const CurrentUserContext = createContext(null);
58 | ```
59 |
60 | ```tsx
61 | const App = () => {
62 | const [currentUser, setCurrentUser] = useState({
63 | username: "filiptammergard",
64 | });
65 |
66 | return (
67 |
68 |
69 |
70 | );
71 | };
72 | ```
73 |
74 | Now that the type of the context can be `null`, you'll notice that you'll get a `'currentUser' is possibly 'null'` TypeScript error if you try to access the `username` property. You can use optional chaining to access `username`:
75 |
76 | ```tsx
77 | import { useContext } from "react";
78 |
79 | const MyComponent = () => {
80 | const currentUser = useContext(CurrentUserContext);
81 |
82 | return
Name: {currentUser?.username}.
;
83 | };
84 | ```
85 |
86 | However, it would be preferable to not have to check for `null`, since we know that the context won't be `null`. One way to do that is to provide a custom hook to use the context, where an error is thrown if the context is not provided:
87 |
88 | ```tsx
89 | import { createContext } from "react";
90 |
91 | interface CurrentUserContextType {
92 | username: string;
93 | }
94 |
95 | const CurrentUserContext = createContext(null);
96 |
97 | const useCurrentUser = () => {
98 | const currentUserContext = useContext(CurrentUserContext);
99 |
100 | if (!currentUserContext) {
101 | throw new Error(
102 | "useCurrentUser has to be used within "
103 | );
104 | }
105 |
106 | return currentUserContext;
107 | };
108 | ```
109 |
110 | Using a runtime type check in this will has the benefit of printing a clear error message in the console when a provider is not wrapping the components properly. Now it's possible to access `currentUser.username` without checking for `null`:
111 |
112 | ```tsx
113 | import { useContext } from "react";
114 |
115 | const MyComponent = () => {
116 | const currentUser = useCurrentUser();
117 |
118 | return
Username: {currentUser.username}.
;
119 | };
120 | ```
121 |
122 | ### Type assertion as an alternative
123 |
124 | Another way to avoid having to check for `null` is to use type assertion to tell TypeScript you know the context is not `null`:
125 |
126 | ```tsx
127 | import { useContext } from "react";
128 |
129 | const MyComponent = () => {
130 | const currentUser = useContext(CurrentUserContext);
131 |
132 | return
Name: {currentUser!.username}.
;
133 | };
134 | ```
135 |
136 | Another option is to use an empty object as default value and cast it to the expected context type:
137 |
138 | ```tsx
139 | const CurrentUserContext = createContext(
140 | {} as CurrentUserContextType
141 | );
142 | ```
143 |
144 | You can also use non-null assertion to get the same result:
145 |
146 | ```tsx
147 | const CurrentUserContext = createContext(null!);
148 | ```
149 |
150 | When you don't know what to choose, prefer runtime checking and throwing over type asserting.
151 |
--------------------------------------------------------------------------------
/docs/basic/getting-started/default-props.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: default_props
3 | title: Typing defaultProps
4 | ---
5 |
6 | ## You May Not Need `defaultProps`
7 |
8 | As per [this tweet](https://twitter.com/dan_abramov/status/1133878326358171650), defaultProps will eventually be deprecated. You can check the discussions here:
9 |
10 | - [Original tweet](https://twitter.com/hswolff/status/1133759319571345408)
11 | - More info can also be found in [this article](https://medium.com/@matanbobi/react-defaultprops-is-dying-whos-the-contender-443c19d9e7f1)
12 |
13 | The consensus is to use object default values.
14 |
15 | Function Components:
16 |
17 | ```tsx
18 | type GreetProps = { age?: number };
19 |
20 | const Greet = ({ age = 21 }: GreetProps) => // etc
21 | ```
22 |
23 | Class Components:
24 |
25 | ```tsx
26 | type GreetProps = {
27 | age?: number;
28 | };
29 |
30 | class Greet extends React.Component {
31 | render() {
32 | const { age = 21 } = this.props;
33 | /*...*/
34 | }
35 | }
36 |
37 | let el = ;
38 | ```
39 |
40 | ## Typing `defaultProps`
41 |
42 | Type inference improved greatly for `defaultProps` in [TypeScript 3.0+](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html), although [some edge cases are still problematic](https://github.com/typescript-cheatsheets/react/issues/61).
43 |
44 | **Function Components**
45 |
46 | ```tsx
47 | // using typeof as a shortcut; note that it hoists!
48 | // you can also declare the type of DefaultProps if you choose
49 | // e.g. https://github.com/typescript-cheatsheets/react/issues/415#issuecomment-841223219
50 | type GreetProps = { age: number } & typeof defaultProps;
51 |
52 | const defaultProps = {
53 | age: 21,
54 | };
55 |
56 | const Greet = (props: GreetProps) => {
57 | // etc
58 | };
59 | Greet.defaultProps = defaultProps;
60 | ```
61 |
62 | _[See this in TS Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcARFDvmQNwBQdMAnmFnAOKVYwAKxY6ALxwA3igDmWAFxwAdgFcQAIyxQ4AXzgAyOM1YQCcACZYCyeQBte-VPVwRZqeCbOXrEAXGEi6cCdLgAJgBGABo6dXo6e0d4TixuLzgACjAbGXjuPg9UAEovAD5RXzhKGHkoWTgAHiNgADcCkTScgDpkSTgAeiQFZVVELvVqrrrGiPpMmFaXcytsz2FZtwXbOiA)_
63 |
64 | For **Class components**, there are [a couple ways to do it](https://github.com/typescript-cheatsheets/react/pull/103#issuecomment-481061483) (including using the `Pick` utility type) but the recommendation is to "reverse" the props definition:
65 |
66 | ```tsx
67 | type GreetProps = typeof Greet.defaultProps & {
68 | age: number;
69 | };
70 |
71 | class Greet extends React.Component {
72 | static defaultProps = {
73 | age: 21,
74 | };
75 | /*...*/
76 | }
77 |
78 | // Type-checks! No type assertions needed!
79 | let el = ;
80 | ```
81 |
82 |
83 | React.JSX.LibraryManagedAttributes nuance for library authors
84 |
85 | The above implementations work fine for App creators, but sometimes you want to be able to export `GreetProps` so that others can consume it. The problem here is that the way `GreetProps` is defined, `age` is a required prop when it isn't because of `defaultProps`.
86 |
87 | The insight to have here is that [`GreetProps` is the _internal_ contract for your component, not the _external_, consumer facing contract](https://github.com/typescript-cheatsheets/react/issues/66#issuecomment-453878710). You could create a separate type specifically for export, or you could make use of the `React.JSX.LibraryManagedAttributes` utility:
88 |
89 | ```tsx
90 | // internal contract, should not be exported out
91 | type GreetProps = {
92 | age: number;
93 | };
94 |
95 | class Greet extends Component {
96 | static defaultProps = { age: 21 };
97 | }
98 |
99 | // external contract
100 | export type ApparentGreetProps = React.JSX.LibraryManagedAttributes<
101 | typeof Greet,
102 | GreetProps
103 | >;
104 | ```
105 |
106 | This will work properly, although hovering over`ApparentGreetProps`may be a little intimidating. You can reduce this boilerplate with the`ComponentProps` utility detailed below.
107 |
108 |
109 |
110 | ## Consuming Props of a Component with defaultProps
111 |
112 | A component with `defaultProps` may seem to have some required props that actually aren't.
113 |
114 | ### Problem Statement
115 |
116 | Here's what you want to do:
117 |
118 | ```tsx
119 | interface IProps {
120 | name: string;
121 | }
122 | const defaultProps = {
123 | age: 25,
124 | };
125 | const GreetComponent = ({ name, age }: IProps & typeof defaultProps) => (
126 |
{`Hello, my name is ${name}, ${age}`}
127 | );
128 | GreetComponent.defaultProps = defaultProps;
129 |
130 | const TestComponent = (props: React.ComponentProps) => {
131 | return ;
132 | };
133 |
134 | // Property 'age' is missing in type '{ name: string; }' but required in type '{ age: number; }'
135 | const el = ;
136 | ```
137 |
138 | ### Solution
139 |
140 | Define a utility that applies `React.JSX.LibraryManagedAttributes`:
141 |
142 | ```tsx
143 | type ComponentProps = T extends
144 | | React.ComponentType
145 | | React.Component
146 | ? React.JSX.LibraryManagedAttributes
147 | : never;
148 |
149 | const TestComponent = (props: ComponentProps) => {
150 | return ;
151 | };
152 |
153 | // No error
154 | const el = ;
155 | ```
156 |
157 | [_See this in TS Playground_](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcARFDvmQNwBQdMAnmFnAMImQB2W3MABWJhUAHgAqAPjgBeOOLhYAHjD4ATdNjwwAdJ3ARe-cSyyjg3AlihwB0gD6Yqu-Tz4xzl67cl04cAH44ACkAZQANHQAZYAAjKGQoJgBZZG5kAHMsNQBBGBgoOIBXVTFxABofPzgALjheADdrejoLVSgCPDYASSEIETgAb2r0kCw61AKLDPoAXzpcQ0m4NSxOooAbQWF0OWH-TPG4ACYAVnK6WfpF7mWAcUosGFdDd1k4AApB+uQxysO4LM6r0dnAAGRwZisCAEFZrZCbbb9VAASlk0g+1VEamADUkgwABgAJLAbDYQSogJg-MZwYDoAAkg1GWFmlSZh1mBNmogA9Di8XQUfQHlgni8jLpVustn0BnJpQjZTsWrzeXANsh2gwbstxFhJhK3nIPmAdnUjfw5WIoVgYXBReKuK9+JI0TJpPs4JQYEUoNw4KIABYARjgvN8VwYargADkIIooMQoAslvBSe8JAbns7JTSsDIyAQIBAyOHJDQgA)
158 |
159 | ## Misc Discussions and Knowledge
160 |
161 |
162 | Why does React.FC break defaultProps?
163 |
164 | You can check the discussions here:
165 |
166 | - https://medium.com/@martin_hotell/10-typescript-pro-tips-patterns-with-or-without-react-5799488d6680
167 | - https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30695
168 | - https://github.com/typescript-cheatsheets/react/issues/87
169 |
170 | This is just the current state and may be fixed in future.
171 |
172 |
173 |
174 |
175 | TypeScript 2.9 and earlier
176 |
177 | For TypeScript 2.9 and earlier, there's more than one way to do it, but this is the best advice we've yet seen:
178 |
179 | ```ts
180 | type Props = Required & {
181 | /* additional props here */
182 | };
183 |
184 | export class MyComponent extends React.Component {
185 | static defaultProps = {
186 | foo: "foo",
187 | };
188 | }
189 | ```
190 |
191 | Our former recommendation used the `Partial type` feature in TypeScript, which means that the current interface will fulfill a partial version on the wrapped interface. In that way we can extend defaultProps without any changes in the types!
192 |
193 | ```ts
194 | interface IMyComponentProps {
195 | firstProp?: string;
196 | secondProp: IPerson[];
197 | }
198 |
199 | export class MyComponent extends React.Component {
200 | public static defaultProps: Partial = {
201 | firstProp: "default",
202 | };
203 | }
204 | ```
205 |
206 | The problem with this approach is it causes complex issues with the type inference working with `React.JSX.LibraryManagedAttributes`. Basically it causes the compiler to think that when creating a JSX expression with that component, that all of its props are optional.
207 |
208 | [See commentary by @ferdaber here](https://github.com/typescript-cheatsheets/react/issues/57) and [here](https://github.com/typescript-cheatsheets/react/issues/61).
209 |
210 |
211 |
212 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
213 |
--------------------------------------------------------------------------------
/docs/basic/getting-started/error-boundaries.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: error_boundaries
3 | title: Error Boundaries
4 | ---
5 |
6 | ### Option 1: Using react-error-boundary
7 |
8 | [React-error-boundary](https://github.com/bvaughn/react-error-boundary) - is a lightweight package ready to use for this scenario with TS support built-in.
9 | This approach also lets you avoid class components that are not that popular anymore.
10 |
11 | ### Option 2: Writing your custom error boundary component
12 |
13 | If you don't want to add a new npm package for this, you can also write your own `ErrorBoundary` component.
14 |
15 | ```jsx
16 | import React, { Component, ErrorInfo, ReactNode } from "react";
17 |
18 | interface Props {
19 | children?: ReactNode;
20 | }
21 |
22 | interface State {
23 | hasError: boolean;
24 | }
25 |
26 | class ErrorBoundary extends Component {
27 | public state: State = {
28 | hasError: false
29 | };
30 |
31 | public static getDerivedStateFromError(_: Error): State {
32 | // Update state so the next render will show the fallback UI.
33 | return { hasError: true };
34 | }
35 |
36 | public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
37 | console.error("Uncaught error:", error, errorInfo);
38 | }
39 |
40 | public render() {
41 | if (this.state.hasError) {
42 | return
Sorry.. there was an error
;
43 | }
44 |
45 | return this.props.children;
46 | }
47 | }
48 |
49 | export default ErrorBoundary;
50 |
51 | ```
52 |
53 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
54 |
--------------------------------------------------------------------------------
/docs/basic/getting-started/forms-and-events.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: forms_and_events
3 | title: Forms and Events
4 | ---
5 |
6 | If performance is not an issue (and it usually isn't!), inlining handlers is easiest as you can just use [type inference and contextual typing](https://www.typescriptlang.org/docs/handbook/type-inference.html#contextual-typing):
7 |
8 | ```tsx
9 | const el = (
10 |