Skip to content

Commit 53dc574

Browse files
committed
Create new Utility Types page and document 11 utilities
1 parent 22b37a2 commit 53dc574

File tree

1 file changed

+223
-0
lines changed

1 file changed

+223
-0
lines changed

pages/Utility Types.md

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
# Introduction
2+
3+
TypeScript provides several utility types to facilitate common type transformations. These utilities are available globally.
4+
5+
# `Partial<T>`
6+
7+
Constructs a type with all properties of `T` set to optional. This utility will return a type that represents all subsets of a given type.
8+
9+
##### Example
10+
11+
```ts
12+
interface Todo {
13+
title: string;
14+
description: string;
15+
}
16+
17+
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
18+
return { ...todo, ...fieldsToUpdate };
19+
}
20+
21+
const todo1 = {
22+
title: 'organize desk',
23+
description: 'clear clutter',
24+
};
25+
26+
const todo2 = updateTodo(todo1, {
27+
description: 'throw out trash',
28+
});
29+
```
30+
31+
# `Readonly<T>`
32+
33+
Constructs a type with all properties of `T` set to `readonly`, meaning the properties of the constructed type cannot be reassigned.
34+
35+
##### Example
36+
37+
```ts
38+
interface Todo {
39+
title: string;
40+
}
41+
42+
const todo: Readonly<Todo> = {
43+
title: 'Delete inactive users',
44+
};
45+
46+
todo.title = 'Hello'; // Error: cannot reassign a readonly property
47+
```
48+
49+
This utility is useful for representing assignment expressions that will fail at runtime (i.e. when attempting to reassign properties of a [frozen object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)).
50+
51+
##### Object.freeze
52+
53+
```ts
54+
function freeze<T>(obj: T): Readonly<T>;
55+
```
56+
57+
# `Record<K, T>`
58+
59+
Constructs a type with a set of properties `K` of type `T`. This utility can be used to map the properties of a type to another type.
60+
61+
##### Example
62+
63+
```ts
64+
interface PageInfo {
65+
title: string;
66+
}
67+
68+
type Page = 'home' | 'about' | 'contact';
69+
70+
const x: Record<Page, PageInfo> = {
71+
about: { title: 'about' },
72+
contact: { title: 'contact' },
73+
home: { title: 'home' },
74+
};
75+
```
76+
77+
# Pick<T, K>
78+
79+
Constructs a type by picking the set of properties `K` from `T`.
80+
81+
##### Example
82+
83+
```ts
84+
interface Todo {
85+
title: string;
86+
description: string;
87+
completed: boolean;
88+
}
89+
90+
type TodoPreview = Pick<Todo, 'title' | 'completed'>;
91+
92+
const todo: TodoPreview = {
93+
title: 'Clean room',
94+
completed: false,
95+
};
96+
```
97+
98+
# Exclude<T, U>
99+
100+
Constructs a type by excluding from `T` all properties that are assignable to `U`.
101+
102+
##### Example
103+
104+
```ts
105+
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
106+
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"
107+
type T2 = Exclude<string | number | (() => void), Function>; // string | number
108+
```
109+
110+
# Extract<T, U>
111+
112+
Constructs a type by extracting from `T` all properties that are assignable to `U`.
113+
114+
##### Example
115+
116+
```ts
117+
type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
118+
type T1 = Extract<string | number | (() => void), Function>; // () => void
119+
```
120+
121+
# NonNullable<T>
122+
123+
Constructs a type by excluding `null` and `undefined` from `T`.
124+
125+
##### Example
126+
127+
```ts
128+
type T0 = NonNullable<string | number | undefined>; // string | number
129+
type T1 = NonNullable<string[] | null | undefined>; // string[]
130+
```
131+
132+
# ReturnType<T>
133+
134+
Constructs a type consisting of the return type of function `T`.
135+
136+
##### Example
137+
138+
```ts
139+
type T0 = ReturnType<() => string>; // string
140+
type T1 = ReturnType<(s: string) => void>; // void
141+
type T2 = ReturnType<(<T>() => T)>; // {}
142+
type T3 = ReturnType<(<T extends U, U extends number[]>() => T)>; // number[]
143+
type T4 = ReturnType<typeof f1>; // { a: number, b: string }
144+
type T5 = ReturnType<any>; // any
145+
type T6 = ReturnType<never>; // any
146+
type T7 = ReturnType<string>; // Error
147+
type T8 = ReturnType<Function>; // Error
148+
```
149+
150+
# InstanceType<T>
151+
152+
Constructs a type consisting of the instance type of a constructor function type `T`.
153+
154+
##### Example
155+
156+
```ts
157+
class C {
158+
x = 0;
159+
y = 0;
160+
}
161+
162+
type T0 = InstanceType<typeof C>; // C
163+
type T1 = InstanceType<any>; // any
164+
type T2 = InstanceType<never>; // any
165+
type T3 = InstanceType<string>; // Error
166+
type T4 = InstanceType<Function>; // Error
167+
```
168+
169+
# Required<T>
170+
171+
Constructs a type consisting of all properties of `T` set to required.
172+
173+
##### Example
174+
175+
```ts
176+
interface Props {
177+
a?: number;
178+
b?: string;
179+
};
180+
181+
const obj: Props = { a: 5 }; // OK
182+
183+
const obj2: Required<Props> = { a: 5 }; // Error: property 'b' missing
184+
```
185+
186+
# ThisType<T>
187+
188+
This utility does not return a transformed type. Instead, it serves a marker for a contextual `this` type. Note that the `--noImplicitThis` flag must be enabled to use this utility.
189+
190+
##### Example
191+
192+
```ts
193+
// Compile with --noImplicitThis
194+
195+
type ObjectDescriptor<D, M> = {
196+
data?: D;
197+
methods?: M & ThisType<D & M>; // Type of 'this' in methods is D & M
198+
}
199+
200+
function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {
201+
let data: object = desc.data || {};
202+
let methods: object = desc.methods || {};
203+
return { ...data, ...methods } as D & M;
204+
}
205+
206+
let obj = makeObject({
207+
data: { x: 0, y: 0 },
208+
methods: {
209+
moveBy(dx: number, dy: number) {
210+
this.x += dx; // Strongly typed this
211+
this.y += dy; // Strongly typed this
212+
}
213+
}
214+
});
215+
216+
obj.x = 10;
217+
obj.y = 20;
218+
obj.moveBy(5, 5);
219+
```
220+
221+
In the example above, the `methods` object in the argument to `makeObject` has a contextual type that includes `ThisType<D & M>` and therefore the type of `this` in methods within the `methods` object is `{ x: number, y: number } & { moveBy(dx: number, dy: number): number }`. Notice how the type of the `methods` property simultaneously is an inference target and a source for the `this` type in methods.
222+
223+
The `ThisType<T>` marker interface is simply an empty interface declared in `lib.d.ts`. Beyond being recognized in the contextual type of an object literal, the interface acts like any empty interface.

0 commit comments

Comments
 (0)