Skip to content

Commit 0ca993b

Browse files
committed
compiler warning
1 parent dfe8f3e commit 0ca993b

1 file changed

Lines changed: 52 additions & 6 deletions

File tree

packages/graphql/letter-to-santa/model-property-error-handling.md

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Proposal: Expressing Model Property Error Handling
22

3-
This proposal suggests adding a two new decorator to the TypeSpec standard library:
3+
This proposal suggests adding two new decorators to the TypeSpec standard library:
44

55
- `@throws` decorator: This decorator is used to specify that the use of a model property may result in specific errors being produced.
66
- `@handles` decorator: This decorator is used to specify that an operation or property will handle certain types of errors, preventing them from being propagated.
@@ -858,7 +858,9 @@ This distinction ensures that the proposal remains flexible and applicable to a
858858

859859
<br>
860860

861-
## Bonus: Adding Context Modifiers to `@error`
861+
## Additional Considerations
862+
863+
### Adding Context Modifiers to `@error`
862864

863865
As an optional enhancement, we propose extending the `@error` decorator to include an argument for specifying context (visibility) modifiers.
864866
This would allow developers to explicitly indicate the contexts in which an error applies, such as input validation, output handling, or both.
@@ -906,11 +908,11 @@ Here, `Lifecycle.CREATE` and `Lifecycle.UPDATE` indicate that `InvalidEmailError
906908
Libraries and emitters should interpret context modifiers, when applied to error models, to determine what errors should be included in different contexts.
907909
This mirrors the [visibility system][visibility-system], and libraries and emitters should interpret the context modifiers the same way as they already do for visibility.
908910

909-
### Examples
911+
#### Examples
910912

911913
The following examples illustrate how the context modifiers can be used in practice.
912914

913-
#### Input Contexts
915+
##### Input Contexts
914916

915917
Errors with `Lifecycle.CREATE`, `Lifecycle.UPDATE`, or `Lifecycle.DELETE` are included when the model is used in an input context.
916918

@@ -920,7 +922,7 @@ Errors with `Lifecycle.CREATE`, `Lifecycle.UPDATE`, or `Lifecycle.DELETE` are in
920922
op createUser(request: User): boolean | InvalidEmailError | GenericError;
921923
```
922924

923-
#### Output Contexts
925+
##### Output Contexts
924926

925927
Errors with `Lifecycle.READ` are included when the model is used in an output context.
926928

@@ -930,7 +932,7 @@ Errors with `Lifecycle.READ` are included when the model is used in an output co
930932
op getUser(@path id: string): User | PermissionDeniedError | GenericError;
931933
```
932934

933-
#### Both Contexts
935+
##### Both Contexts
934936

935937
Errors can apply to both input and output contexts by specifying multiple lifecycle stages.
936938

@@ -941,6 +943,49 @@ model GenericError {
941943
}
942944
```
943945

946+
<br>
947+
948+
### Identifying Unused Error Handlers
949+
950+
TypeSpec only knows, and can only reason about, errors that are specified in a `@throws` decorator.
951+
If an error is specified in a `@handles` decorator but not in any `@throws` decorator of all the model properties that are part of that property or operation, the TypeSpec compiler will not be able to determine whether the error is actually used.
952+
953+
To help developers make that determination, the TypeSpec compiler will issue a warning when this scenario occurs.
954+
If the developer determines that the error _is_ thrown outside of the context of TypeSpec, they can use the standard [`# suppress` directive][suppress-directive] to suppress the warning.
955+
956+
This warning helps to avoid misleading consumers about an error type that may not actually occur.
957+
958+
#### Example: Unused Error Handler
959+
960+
Consider the following example:
961+
962+
```typespec
963+
@error
964+
model NotFoundError {
965+
message: string;
966+
}
967+
968+
@error
969+
model PermissionDeniedError {
970+
message: string;
971+
}
972+
973+
model User {
974+
@throws(NotFoundError)
975+
profilePictureUrl: string;
976+
}
977+
978+
@route("/user/{id}")
979+
@get
980+
@handles(PermissionDeniedError) // warning
981+
op getUser(@path id: string): User;
982+
```
983+
984+
In this example, the `getUser` operation specifies that it handles `PermissionDeniedError` using the `@handles` decorator.
985+
However, none of the properties or operations used in `getUser` (in this case, just the `User.profilePictureUrl` property) specify `PermissionDeniedError` in their `@throws` decorators.
986+
987+
As a result, the TypeSpec compiler will issue a warning.
988+
944989
#
945990

946991
[error-decorator]: https://typespec.io/docs/standard-library/built-in-decorators/#@error
@@ -951,3 +996,4 @@ model GenericError {
951996
[graphql-emitter]: https://github.com/microsoft/typespec/issues/4933
952997
[statuscode-decorator]: https://typespec.io/docs/libraries/http/reference/decorators/#@TypeSpec.Http.statusCode
953998
[visibility-system]: https://typespec.io/docs/language-basics/visibility/
999+
[suppress-directive]: https://typespec.io/docs/language-basics/directives/#suppress

0 commit comments

Comments
 (0)