Skip to content

Commit 57531f1

Browse files
committed
add utility types section
1 parent 6f49b12 commit 57531f1

File tree

1 file changed

+83
-29
lines changed

1 file changed

+83
-29
lines changed

ADVANCED.md

+83-29
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
<summary><b>Expand Table of Contents</b></summary>
1515

16+
- [Section 0: Utility Types](#section-0-utility-types)
1617
- [Section 1: Reusable Components/Type Utilities](#section-1-reusable-componentstype-utilities)
1718
* [Higher Order Components](#higher-order-components-hocs)
1819
* [Render Props](#render-props)
@@ -40,6 +41,88 @@
4041
- [Section 4: @types/react and @types/react-dom APIs](#section-4-typesreact-and-typesreact-dom-apis)
4142
</details>
4243

44+
# Section 0: Utility Types
45+
46+
Handy Utility Types used in the rest of this cheatsheet, or commonly used with React+TS apps, with explanation on what they do and how they can help. We will assume knowledge of [mapped types and conditional types](https://mariusschulz.com/blog/series/typescript-evolution) like `Exclude<T, U>` and `ReturnType<T>` but try to build progressively upon them.
47+
48+
<details>
49+
<summary>
50+
<code>Omit&lt;T, K extends keyof T&gt;</code>: Subtract keys from one interface from the other.
51+
</summary>
52+
53+
```ts
54+
/**
55+
* Subtract keys from one interface from the other.
56+
*
57+
* @example
58+
* interface One { one: string }
59+
* interface Three { one: string, two: string }
60+
*
61+
* type Two = Omit<Three, keyof One>;
62+
*
63+
* // The type of Two will be
64+
* interface Two { two: string }
65+
*/
66+
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
67+
```
68+
69+
You can also supply string literals to omit:
70+
71+
```ts
72+
type SettingsPageProps = Omit<ServerConfig, 'immutableSetting1' | 'invisibleSetting2'>
73+
```
74+
75+
</details>
76+
77+
<details>
78+
<summary>
79+
<code>Optionalize&lt;T extends K, K&gt;</code>: Remove from T the keys that are in common with K
80+
</summary>
81+
82+
```ts
83+
/**
84+
* Remove from T the keys that are in common with K
85+
*/
86+
type Optionalize<T extends K, K> = Omit<T, keyof K>;
87+
```
88+
89+
An example usage is in our HOC section below.
90+
91+
</details>
92+
<details>
93+
<summary>
94+
<code>Nullable&lt;T&gt;</code> or <code>Maybe&lt;T&gt;</code>: Make a Type into a Maybe Type
95+
</summary>
96+
97+
```ts
98+
/**
99+
* Make a Type into a Maybe Type
100+
*/
101+
type Nullable<T> = T | null
102+
type Maybe<T> = T | undefined
103+
```
104+
105+
Your choice of `null` or `undefined` depends on your approach toward missing values. Some folks feel strongly one way or the other.
106+
107+
</details>
108+
<details>
109+
<summary>
110+
<code>Dictionary&lt;T&gt;</code>: Dictionary of string, value pairs
111+
</summary>
112+
113+
```ts
114+
/**
115+
* Dictionary of string, value pairs
116+
*/
117+
type Dictionary<T> = { [key: string]: T }
118+
```
119+
120+
`[key: string]` is a very handy trick in general. You can also modify dictionary fields with [Readonly](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) or make them optional or Omit them, etc.
121+
122+
</details>
123+
124+
[Something to add? File an issue](https://github.com/sw-yx/react-typescript-cheatsheet/issues/new). We respect the fact that naming and selection of examples here is arbitrary as the possible space is infinite.
125+
43126
# Section 1: Advanced Guides
44127
45128
## Higher Order Components (HoCs)
@@ -88,29 +171,6 @@ Now when consuming the component you can omit the `primaryColor` prop or overrid
88171

89172
**Declaring the HoC**
90173

91-
The following utilities will be needed.
92-
93-
```ts
94-
/**
95-
* Generic type utility to subtract keys from one interface from the other.
96-
*
97-
* @example
98-
* interface One { one: string }
99-
* interface Three { one: string, two: string }
100-
*
101-
* type Two = Omit<Three, keyof One>;
102-
*
103-
* // The type of Two will be
104-
* interface Two { two: string }
105-
*/
106-
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
107-
108-
/**
109-
* Remove from T the keys that are in common with K
110-
*/
111-
type Optionalize<T extends K, K> = Omit<T, keyof K>;
112-
```
113-
114174
The actual HoC.
115175

116176
```ts
@@ -222,7 +282,6 @@ function Clickable(props: ButtonProps | AnchorProps) {
222282

223283
They don't even need to be completely different props, as long as they have at least one difference in properties:
224284
```tsx
225-
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
226285
type LinkProps = Omit<JSX.IntrinsicElements[ 'a' ], 'href'> & { to?: string }
227286
228287
function RouterLink(props: LinkProps): JSX.Element
@@ -242,10 +301,7 @@ function RouterLink(props: LinkProps | AnchorProps) {
242301
Here is an example solution, see the further discussion for other solutions. *thanks to [@jpavon](https://github.com/sw-yx/react-typescript-cheatsheet/issues/12#issuecomment-394440577)*
243302

244303
```tsx
245-
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
246-
247304
interface LinkProps {}
248-
249305
type AnchorProps = React.AnchorHTMLAttributes<HTMLAnchorElement>
250306
type RouterLinkProps = Omit<NavLinkProps, 'href'>
251307
@@ -274,8 +330,6 @@ const Link = <T extends {}>(
274330
If you want to conditionally render a component, sometimes is better to use [React's composition model](https://reactjs.org/docs/composition-vs-inheritance.html) to have simpler components and better to understand typings:
275331

276332
```tsx
277-
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
278-
279333
type AnchorProps = React.AnchorHTMLAttributes<HTMLAnchorElement>
280334
type RouterLinkProps = Omit<NavLinkProps, 'href'>
281335

0 commit comments

Comments
 (0)