You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+85-92
Original file line number
Diff line number
Diff line change
@@ -1,4 +1,3 @@
1
-
2
1
:wave: This repo is maintained by [@swyx](https://twitter.com/swyx) and [@IslamAttrash](https://twitter.com/IslamAttrash), we're so happy you want to try out TypeScript with React! This is meant to be an intermediate guide for React developers familiar with the concepts of TypeScript but who are just getting started writing their first React + TypeScript apps. If you see anything wrong or missing, please [file an issue](https://github.com/sw-yx/react-typescript-cheatsheet/issues/new)! :+1:
3
2
4
3
Translations: [中文翻译](https://github.com/fi3ework/blog/tree/master/react-typescript-cheatsheet-cn)*maintained by [@fi3ework](https://github.com/fi3ework/blog/tree/master/react-typescript-cheatsheet-cn)*
Within TypeScript, `React.Component` is a generic type (aka `React.Component<PropType, StateType>`), so you actually want to provide it with prop and (optionally) state types:
144
+
These patterns are not supported:
146
145
147
146
```tsx
148
-
classAppextendsReact.Component<{
149
-
message:string, // it takes one prop called 'message' which is a string type
const el2 = <MyArrayComponentt /> // throws an error
157
152
```
158
153
159
-
If the component has state, here's how to add the types for the state:
154
+
This is because due to limitations in the compiler, function components cannot return anything other than a JSX expression or `null`, otherwise it complains with a cryptic error message saying that the other type is not assignable to `Element`. Unfortunately just annotating the function type will not help so if you really need to return other exotic types that React supports, you'd need to perform a type assertion:
[See commentary by @ferdaber here](https://github.com/sw-yx/react-typescript-cheatsheet/issues/57).
161
+
162
+
</details>
163
+
164
+
## Class Components
165
+
166
+
Within TypeScript, `React.Component` is a generic type (aka `React.Component<PropType, StateType>`), so you want to provide it with (optional) prop and state type parameters:
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. 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.
193
+
194
+
[See commentary by @ferdaber here](https://github.com/sw-yx/react-typescript-cheatsheet/issues/57).
195
+
196
+
</details>
197
+
198
+
199
+
**Class Methods**: Do it like normal, but just remember any arguments for your functions also need to be typed:
179
200
180
201
```tsx
181
202
classAppextendsReact.Component<{
@@ -199,7 +220,7 @@ class App extends React.Component<{
199
220
}
200
221
```
201
222
202
-
If you need to declare class properties for later use, just declare it with a type:
223
+
**Class Properties**: If you need to declare class properties for later use, just declare it like `state`:
203
224
204
225
```tsx
205
226
classAppextendsReact.Component<{
@@ -219,85 +240,44 @@ class App extends React.Component<{
219
240
220
241
[Something to add? File an issue](https://github.com/sw-yx/react-typescript-cheatsheet/issues/new).
221
242
222
-
## Typing DefaultProps
243
+
## Typing defaultProps
223
244
224
-
It is easy to type a defaultProps static member of a React component. There's more than one way to do it, but since we want to show the neatest code as possible
225
-
we chose to propose this way of implementing them:
245
+
There's more than one way to do it, but this is the best advice we've yet seen:
226
246
227
247
```ts
228
-
interfaceIMyComponentProps {
229
-
firstProp?:string;
230
-
secondProp:IPerson[];
231
-
}
248
+
typeProps=Required<typeofMyComponent.defaultProps> & { /* additional props here */ }
This proposal is using `Partial type` feature in TypeScript, which means that the current interface will fulfill a partial
245
-
version on the wrapped interface. In that way we can extend defaultProps without any changes in the types!
246
-
247
-
The other suggestions was related to create a new interface that will look like this:
261
+
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!
The problem with this approach that if we need to add another prop in the future to the defaultProps map then we should update the
267
-
`IMyComponentDefaultProps`!
268
-
</details>
269
-
270
-
[Something to add? File an issue](https://github.com/sw-yx/react-typescript-cheatsheet/issues/new).
276
+
The problem with this approach is it causes complex issues with the type inference working with `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.
271
277
272
-
## Extracting Prop Types
278
+
[See commentary by @ferdaber here](https://github.com/sw-yx/react-typescript-cheatsheet/issues/57).
273
279
274
-
Instead of defining prop types *inline*, you can declare them separately (useful for reusability or code organization):
This can be a bit tricky. The tooling really comes in handy here, as the @type definitions come with a wealth of typing. Type what you are looking for and usually the autocomplete will help you out. Here is what it looks like for an `onChange` for a form event:
347
+
If performance is not an issue, inlining handlers is easiest as you can just use type inference:
360
348
349
+
```tsx
350
+
const el = <buttononClick={event=> {/* ... */}} />
351
+
```
352
+
353
+
But if you need to define your event handler separately, IDE tooling really comes in handy here, as the @type definitions come with a wealth of typing. Type what you are looking for and usually the autocomplete will help you out. Here is what it looks like for an `onChange` for a form event:
361
354
362
355
```tsx
363
356
classAppextendsReact.Component<{}, { // no props
@@ -366,6 +359,9 @@ class App extends React.Component<{}, { // no props
0 commit comments