35 |
36 |
37 |
38 |
39 |
40 |
41 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
42 |
43 |
44 |
45 |
46 |
47 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
48 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/copyFile.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const filesTopCopy = [
3 | {
4 | src: "../CONTRIBUTORS.md",
5 | dest: "../docs/contributors.md",
6 | hideHeader: true,
7 | },
8 | {
9 | src: "../CONTRIBUTING.md",
10 | dest: "../docs/contributing.md",
11 | hideHeader: true,
12 | },
13 | ];
14 |
15 | const generatingPageOptions = `---
16 | hide_title: true
17 | ---
18 |
19 | `;
20 |
21 | function writeNewFile(src, dest) {
22 | const fileContent = fs.readFileSync(src).toString();
23 | const data = new Uint8Array(Buffer.from(generatingPageOptions + fileContent));
24 |
25 | fs.writeFile(dest, data, (err) => {
26 | if (err) {
27 | console.log("Error Found:", err);
28 | } else {
29 | console.log("Files added");
30 | }
31 | });
32 | }
33 |
34 | function copyFile(src, dest) {
35 | fs.copyFile(src, dest, (err) => {
36 | if (err) {
37 | console.log("Error Found:", err);
38 | } else {
39 | console.log("Files copied");
40 | }
41 | });
42 | }
43 |
44 | filesTopCopy.forEach(({ src, dest, hideHeader }) => {
45 | if (hideHeader) {
46 | writeNewFile(src, dest);
47 | } else {
48 | copyFile(src, dest);
49 | }
50 | });
51 |
--------------------------------------------------------------------------------
/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 IMyComponentProps {
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-typescript-cheatsheet/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 | import React from "react";
35 |
36 | interface MyProps {
37 | /** Description of prop "label".
38 | * @default foobar
39 | * */
40 | label?: string;
41 | }
42 |
43 | /**
44 | * General component description in JSDoc format. Markdown is *supported*.
45 | */
46 | export default function MyComponent({ label = "foobar" }: MyProps) {
47 | return
Hello world {label}
;
48 | }
49 | ```
50 |
51 | [View in the TypeScript Playground](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoC4AOxiSk3STgFkBPABRzAGc4BvCnDgB6AFRi4AESQ80UYGBjAI1OBExww3OACIANigBGSfboB0Q4ZIACAEySMArvqwQIRlFCtxJYkVaGJvoA-ABccDwwCtQA5gDcFAC+FBTiYkKSAOJI1PQo+nBouJB5tHAOcgpKKmo0cABSAMpSEGhwmNAgKDDmrF4A1nYQAO51fGI8TmCQsEh2YpbkvgHkSAAes-AOzq4dTtQYtaxsAMIlqrkwABT8cEGmcAC8ep0eXrpwSRHsXBC8AEoBFYiDAnFA1AAeOzAABuAD4ABKmfQQOAjaD6OwCB76JKQkQwhGJchJIA)
52 |
53 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/new).
54 |
55 | ## Namespaced Components
56 |
57 | 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()`;
58 |
59 | ```tsx
60 | import React from "react";
61 |
62 | const Input = (props: any) => ;
63 |
64 | const Form = React.forwardRef(
65 | ({ children, ...otherProps }, ref) => (
66 |
69 | )
70 | );
71 |
72 | /**
73 | * Exported components now can be used as ``
74 | */
75 | export default Object.assign(Form, { Input: Input });
76 | ```
77 |
78 | [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)
79 |
80 | (Contributed by @bryceosterhaus, see [further discussion](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/165))
81 |
82 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/new).
83 |
84 | ## Design System Development
85 |
86 | 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)
87 |
88 | For developing with Storybook, read the docs I wrote over here: . This includes automatic proptype documentation generation, which is awesome :)
89 |
90 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/new).
91 |
92 | ## Migrating From Flow
93 |
94 | You should check out large projects that are migrating from flow to pick up concerns and tips:
95 |
96 | - [Jest](https://github.com/facebook/jest/pull/7554)
97 | - [Expo](https://github.com/expo/expo/issues/2164)
98 | - [React-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd/issues/982)
99 | - [Storybook](https://github.com/storybooks/storybook/issues/5030)
100 | - [VueJS](https://medium.com/the-vue-point/plans-for-the-next-iteration-of-vue-js-777ffea6fabf)
101 |
102 | Useful libraries:
103 |
104 | -
105 | -
106 | -
107 |
108 | If you have specific advice in this area, please file a PR!
109 |
110 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/new).
111 |
112 | ## Prettier
113 |
114 | There isn't any real secret to Prettier for TypeScript. But its a great idea to run prettier on every commit!
115 |
116 | ```bash
117 | $ yarn add -D prettier husky lint-staged
118 | ```
119 |
120 | ```json
121 | // inside package.json
122 | {
123 | //...
124 | "husky": {
125 | "hooks": {
126 | "pre-commit": "lint-staged"
127 | }
128 | },
129 | "lint-staged": {
130 | "linters": {
131 | "src/*.{ts,tsx,js,jsx,css,scss,md}": [
132 | "prettier --trailing-comma es5 --single-quote --write",
133 | "git add"
134 | ],
135 | "ignore": ["**/dist/*, **/node_modules/*"]
136 | }
137 | },
138 | "prettier": {
139 | "printWidth": 80,
140 | "semi": false,
141 | "singleQuote": true,
142 | "trailingComma": "es5"
143 | }
144 | }
145 | ```
146 |
147 | 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)
148 |
149 | 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.
150 |
151 | ## Testing
152 |
153 | Yes, you can test your types! You shouldn't use it for EVERYTHING, but it can help prevent regressions:
154 |
155 | - https://github.com/azz/jest-runner-tsc
156 | - https://github.com/SamVerschueren/tsd
157 | - https://github.com/ikatyang/dts-jest ([Demo](https://codesandbox.io/s/dts-test-frozen-public-demo-iyorn))
158 | - https://github.com/microsoft/dtslint ([Intro to dtslint](https://www.youtube.com/watch?v=nygcFEwOG8w&feature=share))
159 |
160 | ## Working with Non-TypeScript Libraries (writing your own index.d.ts)
161 |
162 | Lets say you want to use `de-indent`, but it isn't typed or on DefinitelyTyped. You get an error like this:
163 |
164 | ```
165 | [ts]
166 | 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.
167 | Try `npm install @types/de-indent` if it exists or add a new declaration (.d.ts) file containing `declare module 'de-indent';` [7016]
168 | ```
169 |
170 | So create a `.d.ts` file anywhere in your project with the module definition:
171 |
172 | ```ts
173 | // de-indent.d.ts
174 | declare module "de-indent" {
175 | function deindent(): void;
176 | export = deindent; // default export
177 | }
178 | ```
179 |
180 |
181 |
182 | Further Discussion
183 |
184 | Any other tips? Please contribute on this topic! [We have an ongoing issue here with some references](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/8). We have more discussion and examples [in our issue here](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/12).
185 |
186 |
187 |
188 | ## Compilation Speed
189 |
190 | Compiling large TS projects can get slow. Here are some tips:
191 |
192 | - We have a dedicated repo tracking TS speed recommendations: https://github.com/typescript-cheatsheets/speed
193 | - Use [TS 3.0 Project references](https://react-typescript-cheatsheet.netlify.app/docs/advanced/patterns_by_version#typescript-30)
194 | - 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)
195 | - Webpack ([see CRA diff](https://gist.github.com/jaredpalmer/d3016701589f14df8a3572df91a5754b)):
196 | - set `output.pathinfo = false`
197 | - set `optimization.splitChunks`, `optimization.removeAvailableModules`, `optimization.removeEmptyChunks` to `false`
198 |
--------------------------------------------------------------------------------
/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`, `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-typescript-cheatsheet/pull/69): I discourage the use of most `...Element` types because of how black-boxy `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 have a good working knowledge of how to construct the inbuilt utility types from scratch. See [Dr. Rasuchmeyer'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 | /** any object as long as you dont use its properties (NOT COMMON but useful as placeholder) */
22 | obj: object;
23 | obj2: {}; // almost the same as `object`, exactly the same as `Object`
24 | /** an object with any number of properties (PREFERRED) */
25 | obj3: {
26 | id: string;
27 | title: string;
28 | };
29 | /** array of objects! (common) */
30 | objArr: {
31 | id: string;
32 | title: string;
33 | }[];
34 | /** a dict object with any number of properties of the same type */
35 | dict1: {
36 | [key: string]: MyTypeHere;
37 | };
38 | dict2: Record; // equivalent to dict1
39 | /** any function as long as you don't invoke it (not recommended) */
40 | onSomething: Function;
41 | /** function that doesn't take or return anything (VERY COMMON) */
42 | onClick: () => void;
43 | /** function with named prop (VERY COMMON) */
44 | onChange: (id: number) => void;
45 | /** alternative function type syntax that takes an event (VERY COMMON) */
46 | onClick(event: React.MouseEvent): void;
47 | /** an optional prop (VERY COMMON!) */
48 | optional?: OptionalType;
49 | };
50 | ```
51 |
52 | Notice we have used the TSDoc `/** comment */` style here on each prop. You can and are encouraged to leave descriptive comments on reusable components. For a fuller example and discussion, see our [Commenting Components](https://react-typescript-cheatsheet.netlify.app/docs/advanced/misc_concerns/#commenting-components) section in the Advanced Cheatsheet.
53 |
54 | ## Useful React Prop Type Examples
55 |
56 | Relevant for components that accept other React components as props.
57 |
58 | ```tsx
59 | export declare interface AppProps {
60 | children1: JSX.Element; // bad, doesnt account for arrays
61 | children2: JSX.Element | JSX.Element[]; // meh, doesn't accept strings
62 | children3: React.ReactChildren; // despite the name, not at all an appropriate type; it is a utility
63 | children4: React.ReactChild[]; // better, accepts array children
64 | children: React.ReactNode; // best, accepts everything (see edge case below)
65 | functionChildren: (name: string) => React.ReactNode; // recommended function as a child render prop type
66 | style?: React.CSSProperties; // to pass through style props
67 | onChange?: React.FormEventHandler; // form events! the generic parameter is the type of event.target
68 | // more info: https://react-typescript-cheatsheet.netlify.app/docs/advanced/patterns_by_usecase/#wrappingmirroring
69 | props: Props & React.ComponentPropsWithoutRef<"button">; // to impersonate all the props of a button element and explicitly not forwarding its ref
70 | props2: Props & React.ComponentPropsWithRef; // to impersonate all the props of MyButtonForwardedRef and explicitly forwarding its ref
71 | }
72 | ```
73 |
74 |
75 |
76 | Small `React.ReactNode` edge case
77 |
78 |
79 | This code typechecks but has a runtime error:
80 |
81 | ```tsx
82 | type Props = {
83 | children: React.ReactNode;
84 | };
85 |
86 | function Comp({ children }: Props) {
87 | return
{children}
;
88 | }
89 | function App() {
90 | return {{}}; // Runtime Error: Objects not valid as React Child!
91 | }
92 | ```
93 |
94 | This is because `ReactNode` includes `ReactFragment` which allows a `{}` type, which is [too wide](https://github.com/DefinitelyTyped/DefinitelyTyped/issues/37596#issue-480260937). Fixing this would break a lot of libraries, so for now you just have to be mindful that `ReactNode` is not absolutely bulletproof.
95 |
96 | [Thanks @pomle for raising this.](https://github.com/typescript-cheatsheets/react/issues/357)
97 |
98 |
99 |
100 |
101 | JSX.Element vs React.ReactNode?
102 |
103 | Quote [@ferdaber](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/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 `JSX.Element` interface, but `React.ReactNode` is the set of all possible return values of a component.
104 |
105 | - `JSX.Element` -> Return value of `React.createElement`
106 | - `React.ReactNode` -> Return value of a component
107 |
108 |
109 |
110 | [More discussion: Where ReactNode does not overlap with JSX.Element](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/129)
111 |
112 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/new).
113 |
114 | ## Types or Interfaces?
115 |
116 | You can use either Types or Interfaces to type Props and State, so naturally the question arises - which do you use?
117 |
118 | ### TL;DR
119 |
120 | Use Interface until You Need Type - [orta](https://twitter.com/orta/status/1356129195835973632?s=20).
121 |
122 | ### More Advice
123 |
124 | Here's a helpful rule of thumb:
125 |
126 | - 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.
127 |
128 | - consider using `type` for your React Component Props and State, for consistency and because it is more constrained.
129 |
130 | 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).
131 |
132 | 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).
133 |
134 | > 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)
135 |
136 | 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.
137 |
138 | ### Useful table for Types vs Interfaces
139 |
140 | It's a nuanced topic, don't get too hung up on it. Here's a handy table:
141 |
142 | | Aspect | Type | Interface |
143 | | ----------------------------------------------- | :--: | :-------: |
144 | | Can describe functions | ✅ | ✅ |
145 | | Can describe constructors | ✅ | ✅ |
146 | | Can describe tuples | ✅ | ✅ |
147 | | Interfaces can extend it | ⚠️ | ✅ |
148 | | Classes can extend it | 🚫 | ✅ |
149 | | Classes can implement it (`implements`) | ⚠️ | ✅ |
150 | | Can intersect another one of its kind | ✅ | ⚠️ |
151 | | Can create a union with another one of its kind | ✅ | 🚫 |
152 | | Can be used to create mapped types | ✅ | 🚫 |
153 | | Can be mapped over with mapped types | ✅ | ✅ |
154 | | Expands in error messages and logs | ✅ | 🚫 |
155 | | Can be augmented | 🚫 | ✅ |
156 | | Can be recursive | ⚠️ | ✅ |
157 |
158 | ⚠️ In some cases
159 |
160 | (source: [Karol Majewski](https://twitter.com/karoljmajewski/status/1082413696075382785))
161 |
162 | [Something to add? File an issue](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/new).
163 |
--------------------------------------------------------------------------------
/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-typescript-cheatsheet/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 |
40 | );
41 | };
42 | ```
43 |
44 | You can also use the [Class.contextType](https://reactjs.org/docs/context.html#classcontexttype) or [Context.Consumer](https://reactjs.org/docs/context.html#contextconsumer) API, let us know if you have trouble with that.
45 |
46 | _[Thanks to @AlvSovereign](https://github.com/typescript-cheatsheets/react/issues/97)_
47 |
48 | ## Extended Example
49 |
50 | Using `React.createContext` with an empty object as default value.
51 |
52 | ```tsx
53 | interface ContextState {
54 | // set the type of state you want to handle with context e.g.
55 | name: string | null;
56 | }
57 | //set an empty object as default state
58 | const Context = React.createContext({} as ContextState);
59 | // set up context provider as you normally would in JavaScript [React Context API](https://reactjs.org/docs/context.html#api)
60 | ```
61 |
62 | Using `React.createContext` and [context getters](https://kentcdodds.com/blog/application-state-management-with-react/) to make a `createCtx` with **no `defaultValue`, yet no need to check for `undefined`**:
63 |
64 | ```ts
65 | import * as React from "react";
66 |
67 | const currentUserContext = React.createContext(undefined);
68 |
69 | function EnthusasticGreeting() {
70 | const currentUser = React.useContext(currentUserContext);
71 | return
HELLO {currentUser!.toUpperCase()}!
;
72 | }
73 |
74 | function App() {
75 | return (
76 |
77 |
78 |
79 | );
80 | }
81 | ```
82 |
83 | Notice the explicit type arguments which we need because we don't have a default `string` value:
84 |
85 | ```ts
86 | const currentUserContext = React.createContext(undefined);
87 | // ^^^^^^^^^^^^^^^^^^
88 | ```
89 |
90 | along with the non-null assertion to tell TypeScript that `currentUser` is definitely going to be there:
91 |
92 | ```ts
93 | return