This page documents emitter behavior and customization when you use union operator |
or @sharedRoute
to express multiple input/output for a given path.
Default behaviors
The simplest way to express a combination of input in TypeSpec is to use the union operator |
.
At a glance, JS and Python supports natively union, while Java and C# will use overloads.
op analyze ( @query mode : "strict" | "lenient" , @body image : bytes ) : AnalyzeResult ;
input : string | string [];
op completions ( @body input : CompletionInput ) : CompletionResult ;
def analyze (image: bytes , * , mode: Literal[ "strict" , "lenient" ]) -> AnalyzeResult:
input : Union[ str , List[ str ]] = rest_field( readonly = True )
def completions (input: CompletionInput) -> CompletionResult:
// Union "strict" | "lenient" will be generate as extensible enum
public readonly partial struct Mode : IEquatable < Mode >
public static Mode Strict { get ; } = new Mode (StrictValue);
public static Mode Lenient { get ; } = new Mode (LenientValue);
// other union which cannot be convert to enum will generate as BinaryData
public partial class CompletionInput
public CompletionInput ( BinaryData input )
public BinaryData Input { get; }
public partial class AnalyzeClient
public virtual async Task < Response > AnalyzeAsync ( string mode , RequestContent content , RequestContext context = null ) {}
public virtual Response Analyze ( string mode , RequestContent content , RequestContext context = null ) {}
public virtual async Task < Response < AnalyzeResult >> AnalyzeAsync ( Mode mode , BinaryData image , CancellationToken cancellationToken = default ) {}
public virtual Response < AnalyzeResult > Analyze ( Mode mode , BinaryData image , CancellationToken cancellationToken = default ) {}
public virtual async Task < Response > CompletionsAsync ( RequestContent content , RequestContext context = null ) {}
public virtual Response Completions ( RequestContent content , RequestContext context = null ) {}
public virtual async Task < Response < CompletionResult >> CompletionsAsync ( CompletionInput input , CancellationToken cancellationToken = default ) {}
public virtual Response < CompletionResult > Completions ( CompletionInput input , CancellationToken cancellationToken = default ) {}
// from user experience perspective
export interface CompletionInput {
input : string | string [];
export type DemoServiceContext = Client & {
/** Resource for '/analyze' has methods for the following verbs: post */
mode : "strict" | "lenient" ;
) : StreamableMethod < Analyze200Response | AnalyzeDefaultResponse >;
/** Resource for '/completions' has methods for the following verbs: post */
( path : "/completions" ) : {
) : StreamableMethod < Completions200Response | CompletionsDefaultResponse >;
public final class CompletionInput {
public CompletionInput (BinaryData input )
public BinaryData getInput ()
public final class AnalyzeClient {
public Response< BinaryData > analyzeWithResponse (String mode , BinaryData image , RequestOptions requestOptions )
public Response< BinaryData > completionsWithResponse (BinaryData input , RequestOptions requestOptions )
public AnalyzeResult analyze (Mode mode , byte [] image )
public CompletionResult completions (CompletionInput input )
Using union implies that the entire combination of possible input is valid. If you have a specific set of combination, or connection between input and output,
you must use @sharedRoute
. By default, codegen will generate one method per operation name.
public Response A ( RequestContent content , RequestContext context );
public Response B ( RequestContent content , RequestContext context );
public Response < float > A ( int x , CancellationToken token );
public Response < long > B ( string x , Cancellation token );
// from user experience perspective
export type DemoServiceContext = Client & {
/** Resource for '/foo' has methods for the following verbs: post */
) : StreamableMethod < A200Response >;
) : StreamableMethod < B200Response >;
public final class Client {
public Response< BinaryData > aWithResponse (BinaryData request , RequestOptions requestOptions )
public Response< BinaryData > bWithResponse (BinaryData request , RequestOptions requestOptions )
Customizations
Merge @sharedRoute
operations into one.
If your shared routes are actually one unique semantic operation, you may want to configure codegen to use a unique name. This is simply done by renaming both operations to the same name using @clientName
import "@azure-tools/typespec-client-generator-core" ;
using Azure . ClientGenerator . Core ;
def foo (x: int ) -> float :
def foo (x: string) -> int :
def foo (x: string | int ) -> float | int :
public Response Foo ( RequestContent content , RequestContext context );
public Response < float > Foo ( int x , CancellationToken token );
public Response < long > Foo ( string x , Cancellation token );
JS RLC is not in the business of customization with client.tsp