microsoft / microsoft/typespec
Proposal: Introduce `interface is` and `interface ...` operators
- Dominant language
- Java
- Stars
- 5.9k
- Forks
- 394
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 104
Description
### Clear and concise description of the problem
Following the steps of [this discussion](https://github.com/microsoft/typespec/discussions/7178) I'd like to propose to add is operator for interfaces.
This allows for some way of operations sharing in packs and modularization, instead of per operations reinstantiation.
E.g. having some base interface defined in an isolated module, `interface is` would allow for complete instantiation.
Identity module.
```typespec
import "@typespec/http";
import "./common.tsp";
using Http;
namespace Identity;
model Key {
id: uuid;
}
model Entity {
...Key;
...EntityTimestamps;
name?: string;
email: email;
}
@route("/identities")
@tag("identity")
@useAuth(BearerAuth)
interface Service {
@get
@summary("Get identity by id")
get(@path identityId: string): (OkResponse &
Body) | NotFoundResponse;
@patch
@summary("Patch identity")
patch(
@path identityId: string,
...MergePatchUpdate>,
): NoContentResponse;
}
```
There's currently no way to share things in a bigger scopes, that per operation. In order to bring this example to life (some external namespace) I'd have to do this:
```typespec
import "@typespec/http";
import "./identity.tsp";
using Http;
@service()
namespace MyAPI;
interface IdentityService {
get is Identity.Service.get;
patch is Identity.Service.patch;
}
```
Note, that even in this case it's not fully working as expected:
Interface level decorators does not have effect on each operation, so actual route path, tag and auth are missing.
So, instead, I'm proposing to introduce two operators which we have already for entities. In this case my example transforms into this solution
```typespec
import "@typespec/http";
import "./identity.tsp";
using Http;
@service()
namespace MyAPI;
interface IdentityService is Identity.Service;
// equivalent to
@route("/identities")
@tag("identity")
@useAuth(BearerAuth)
interface IdentityService {
get is Identity.Service.get;
patch is Identity.Service.patch;
}
```
Is will carry out all operations will all decorators on them and interface level decorators as well. Logic is pretty much the same as with entities.
Alternatively, omitting interface level decorators for some reasons, one can use spread operator to populate and filter operations on an interface.
```typespec
import "@typespec/http";
import "./identity.tsp";
using Http;
@service()
namespace MyAPI;
interface IdentityService {
...PickProperties
}
//equals to
interface IdentityService {
get is Identity.Service.get;
}
```
### Checklist
- [x] Follow our [Code of Conduct](https://github.com/microsoft/typespec/blob/main/CODE_OF_CONDUCT.md)
- [x] Read the [docs](https://typespec.io/docs/).
- [x] Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
Contributor guide
Assessment
This issue has not been assessed yet.