diff --git a/README.md b/README.md
index 2a5a2d56..8cfb13c5 100644
--- a/README.md
+++ b/README.md
@@ -158,10 +158,10 @@
- [Using Partial Types](#using-partial-types)
- [The Types I need weren't exported!](#the-types-i-need-werent-exported)
- [The Types I need don't exist!](#the-types-i-need-dont-exist)
- - [Slapping `any` on everything](#slapping-any-on-everything)
- - [Autogenerate types](#autogenerate-types)
- - [Typing Exported Hooks](#typing-exported-hooks)
- - [Typing Exported Components](#typing-exported-components)
+ * [Slapping `any` on everything](#slapping-any-on-everything)
+ * [Autogenerate types](#autogenerate-types)
+ * [Typing Exported Hooks](#typing-exported-hooks)
+ * [Typing Exported Components](#typing-exported-components)
- [Troubleshooting Handbook: Operators](#troubleshooting-handbook-operators)
- [Troubleshooting Handbook: Utilties](#troubleshooting-handbook-utilities)
- [Troubleshooting Handbook: tsconfig.json](#troubleshooting-handbook-tsconfigjson)
@@ -177,7 +177,6 @@
-
# Section 1: Setup TypeScript with React
## Prerequisites
@@ -255,14 +254,24 @@ You should also check [the new TypeScript docs for official descriptions between
# Section 2: Getting Started
-
## Function Components
These can be written as normal functions that take a `props` argument and return a JSX element.
```tsx
-type AppProps = { message: string }; /* could also use interface */
+// Declaring type of props - see "Typing Component Props" for more examples
+type AppProps = {
+ message: string;
+}; /* use `interface` if exporting so that consumers can extend */
+
+// Easiest way to declare a Function Component; return type is inferred.
const App = ({ message }: AppProps) =>
{message}
;
+
+// you can choose annotate the return type so an error is raised if you accidentally return some other type
+const App = ({ message }: AppProps): JSX.Element =>
{message}
;
+
+// you can also inline the type declaration; eliminates naming the prop types, but looks repetitive
+const App = ({ message }: { message: string }) =>
{message}
;
```
@@ -297,11 +306,7 @@ const Title: React.FunctionComponent<{ title: string }> = ({
```
-
-
-Using `React.VoidFunctionComponent` or `React.VFC` instead
-
-
+Using `React.VoidFunctionComponent` or `React.VFC` instead
As of [@types/react 16.9.48](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/46643), you can also use `React.VoidFunctionComponent` or `React.VFC` type if you want to type `children` explicitly. This is an interim solution until `FunctionComponent` will accept no children by default (planned for `@types/react@^18.0.0`).
@@ -377,14 +382,13 @@ const MyArrayComponent = () => (Array(5).fill() as any) as JSX.Element;
-
## Hooks
Hooks are [supported in `@types/react` from v16.8 up](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/a05cc538a42243c632f054e42eab483ebf1560ab/types/react/index.d.ts#L800-L1031).
## useState
-Type inference works very well most of the time:
+Type inference works very well for simple values:
```tsx
const [val, toggle] = React.useState(false);
@@ -403,6 +407,17 @@ const [user, setUser] = React.useState(null);
setUser(newUser);
```
+You can also use type assertions if a state is initialized soon after setup and always has a value after:
+
+```tsx
+const [user, setUser] = React.useState({} as IUser);
+
+// later...
+setUser(newUser);
+```
+
+This temporarily "lies" to the TypeScript compiler that `{}` is of type `IUser`. You should follow up by setting the `user` state — if you don't, the rest of your code may rely on the fact that `user` is of type `IUser` and that may lead to runtime errors.
+
## useReducer
You can use [Discriminated Unions](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#discriminated-unions) for reducer actions. Don't forget to define the return type of reducer, otherwise TypeScript will infer it.
@@ -533,7 +548,7 @@ function MyComponent() {
-The second option will infer a `RefObject` instead of a `MutableRefObject`. This means there will be a type error ifyou try to assign to `ref2.current`.
+The second option will infer a `RefObject` instead of a `MutableRefObject`. This means there will be a type error if you try to assign to `ref2.current`.
The third option will make `ref3.current` mutable, and is intended for "instance variables" that you manage yourself.
@@ -661,7 +676,6 @@ If you are writing a React Hooks library, don't forget that you should also expo
-
## Class Components
Within TypeScript, `React.Component` is a generic type (aka `React.Component`), so you want to provide it with (optional) prop and state type parameters:
@@ -836,7 +850,6 @@ class Comp extends React.PureComponent {
-
## You May Not Need `defaultProps`
As per [this tweet](https://twitter.com/dan_abramov/status/1133878326358171650), defaultProps will eventually be deprecated. You can check the discussions here:
@@ -936,7 +949,7 @@ export type ApparentGreetProps = JSX.LibraryManagedAttributes<
>;
```
-``This will work properly, although hovering over`ApparentGreetProps`may be a little intimidating. You can reduce this boilerplate with the`ComponentProps` utility detailed below.
+This will work properly, although hovering over`ApparentGreetProps`may be a little intimidating. You can reduce this boilerplate with the`ComponentProps` utility detailed below.
@@ -1047,7 +1060,6 @@ The problem with this approach is it causes complex issues with the type inferen
-
## Typing Component Props
This is intended as a basic orientation and reference for React developers familiarizing with TypeScript.
@@ -1279,7 +1291,6 @@ class Comp extends React.PureComponent {
-
## Forms and Events
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):
@@ -1340,7 +1351,7 @@ The first method uses an inferred method signature `(e: React.FormEvent`, `