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: apps/docs/docs/nest.md
+55-43Lines changed: 55 additions & 43 deletions
Original file line number
Diff line number
Diff line change
@@ -1,19 +1,25 @@
1
1
# Nest
2
2
3
-
By default Nest doesn't offer a nice way to ensure type safe controllers, primarily because it's decorator driven rather than functional, like Express.
3
+
As opposed to the Express implementation, where we can infer types from a function signature, we need to explicitly define our types since Nest controllers are implemented as classes.
async getPost(@ApiDecorator() { params: { id } }:RouteShape['getPost']) {
21
+
@Api(c.getPost)
22
+
async getPost(@TsRestRequest() { params: { id } }:RequestShapes['getPost']) {
17
23
const post =awaitthis.postService.getPost(id);
18
24
19
25
if (!post) {
@@ -25,9 +31,17 @@ export class PostController implements ControllerShape {
25
31
}
26
32
```
27
33
34
+
The `nestControllerContract` filters your contract to only include immediate routes and no nested routes. Otherwise, you'd have to implement the entire contract in a single controller. As a result, it's good practice to design your contract into multiple nested contracts, one for each controller.
35
+
36
+
To implement a nested contract, you can simply call `nestControllerContract(contract.nestedContract)`
37
+
38
+
Having the controller class implement `NestControllerInterface` ensures that your controller implements all the routes defined in the contract. In addition, it ensures the type safety of the responses returned.
39
+
28
40
The `@Api` decorator takes the route, defines the path and method for the controller route.
29
41
30
-
It also injects "appRoute" into the req object, allowing the `@ApiDecorator` decorator automatically parse and check the query and body parameters.
42
+
The `@TsRestRequest` decorator takes the contract route defined in the `@Api` decorator, and returns the parsed and validated (if using Zod) request params, query and body.
43
+
44
+
As Typescript cannot infer class method parameter types from an implemented interface, we need to explicitly define the type for the request parameter using the `NestRequestShapes` type.
31
45
32
46
## JSON Query Parameters
33
47
@@ -36,63 +50,61 @@ To handle JSON query parameters, you can use the `@JsonQuery()` decorator on eit
async getPost(@ApiDecorator() { params: { id } }:RouteShape['getPost']) {
66
+
async getPost(@TsRestRequest() { params: { id } }:RequestShapes['getPost']) {
53
67
// ...
54
68
}
55
69
}
56
70
```
57
71
58
-
## Response Return Type Safety
59
-
60
-
You have two options to ensure HTTP type safety on your Nest Controllers:
61
-
62
-
-`ControllerShape` as shown above:
63
-
- Your controller can implement the `ControllerShape` derived from `typeof s.controllerShape`
64
-
- This ensures your controller methods also align with the base interface shapes
65
-
-`ResponseShapes`:
72
+
## Explicit Response Type Safety
66
73
67
-
- Your controller can utilize `typeof s.responseShapes` in the return type. For example:
74
+
In cases where you do not want to implement `NestControllerInterface`.
75
+
Say, if you were to implement a contract's non-nested routes across multiple controllers, or use different class method names than the ones defined in your contract, you can still ensure type safety of the responses by using the `NestResponseShapes` type.
68
76
69
-
```typescript
70
-
const s =initNestServer(apiBlog);
71
-
typeControllerShape=typeofs.controllerShape;
72
-
typeRouteShape=typeofs.routeShapes;
73
-
typeResponseShapes=typeofs.responseShapes; // <- http Responses defined in contract
0 commit comments