- 
                Notifications
    You must be signed in to change notification settings 
- Fork 317
Description
One of the bits of magic happening in the rest framework is establishing common parameters and return types for resource interfaces. This has two drawbacks - one, the behavior is accomplished via decorators and so is fairly opaque, and two, custom operations on the interface need to provide the correct (and possibly very complex) parameters themselves.
This problem could be solved in part by going back to one of the very early designs for interfaces which had an interface-level parameter list, but this approach itself has some drawbacks - it doesn't address return types, and it is inflexible in terms of the position of the parameters (i.e., they always came first).
With the addition of templates, we can probably do something better. A basic proposal (names up for bikeshedding) is to add a special operation called opTemplate which takes template parameters for the original arguments and original return type and can be decorated. When Cadl instantiates operations, it runs the opTemplate for any mixed interfaces and the parent interface.
A resource could then look like:
interface MyResource mixes ReadResource<Foo> {
  // add the error response and apply @commonDec to all members
  @commonDec
  opTemplate<TParams, TReturn>(... TParams): TReturn | ErrorResponse;
  // also has the common parameters from the parent interface
  customRead(): Foo;
}
interface ReadResource<T> {
  opTemplate<TParams, TReturn>(... @KeyParameters<T>, ... TParams): TReturn
  @get read(): T;
}
It might be tempting to use this mechanism to wrap everything in the Response envelope, however because cadl unions are never distributive, this won't work without some further modifications:
interface MyResource extends ReadResource<Foo> {
  returnType<TDeclReturn> = Response<TDeclReturn | Error>
  // Now has a return type of Response<Foo | Bar | Error>
  customRead(): Foo | Bar;
}
(TypeScript has the ability for a particular template to opt-in to distributivity via a weird hack but this wouldn't really work for us anyway since I think we need template call sites to specify whether they intend a union to be distributive or not. Though we could have a DistributiveResponse template that uses a callee-side hack ala TypeScript I suppose.)
It might also be interesting to consider similar mechanisms for models and even other declarations, though I don't have any scenarios in mind at the moment.