Client Options
This page documents how to use the @clientOption decorator to pass language-specific configuration options to emitters. For an overview of the setup, please visit the setup page.
Overview
Section titled “Overview”The @clientOption decorator allows spec authors to pass arbitrary key-value options to specific language emitters. This enables fine-grained control over code generation behavior that may vary between languages.
@clientOption(name: string, value: unknown, scope?: string)Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
name | string | The name of the option to set |
value | unknown | The option value. Primitive, array, object, and nested values are supported; the consuming emitter determines the expected shape. |
scope | string (syntax optional) | The target language scope. Every use must provide an explicit scope; omitting it produces a decorator-requires-scope warning. |
The declaration keeps scope syntactically optional so TCGC can report a targeted diagnostic for legacy unscoped uses. New and updated specifications must always provide it.
Basic Usage
Section titled “Basic Usage”Apply the decorator to models, operations, enums, properties, namespaces, or interfaces with a language-specific scope:
import "@azure-tools/typespec-client-generator-core";
using Azure.ClientGenerator.Core;
#suppress "@azure-tools/typespec-client-generator-core/client-option"@clientOption("enableFeatureFoo", true, "python")model MyModel { id: string;}# The Python emitter can read this option from the model's decorators array# and apply the appropriate code generation behavior// C# emitter does not see this option (scoped to Python only)// TypeScript emitter does not see this option (scoped to Python only)// Java emitter does not see this option (scoped to Python only)// Go emitter does not see this option (scoped to Python only)Multiple Options
Section titled “Multiple Options”You can apply multiple @clientOption decorators to the same target:
#suppress "@azure-tools/typespec-client-generator-core/client-option"@clientOption("enableFeatureFoo", true, "python")@clientOption("customSerializerMode", "strict", "python")model MyModel { id: string;}Different Value Types
Section titled “Different Value Types”The decorator supports arbitrary values, including primitives, arrays, objects, and nested combinations:
#suppress "@azure-tools/typespec-client-generator-core/client-option"@clientOption("booleanOption", true, "python")model BoolExample { id: string;}
#suppress "@azure-tools/typespec-client-generator-core/client-option"@clientOption("stringOption", "customValue", "csharp")model StringExample { id: string;}
#suppress "@azure-tools/typespec-client-generator-core/client-option"@clientOption("numericOption", 42, "java")model NumericExample { id: string;}
#suppress "@azure-tools/typespec-client-generator-core/client-option"@clientOption("structuredOption", #{ mode: "strict", retries: #[1, 2, 3] }, "python")model StructuredExample { id: string;}How Emitters Access Client Options
Section titled “How Emitters Access Client Options”TCGC provides the getClientOptions helper function to extract an option by name from any decorated SDK type.
Using the getClientOptions Helper (Recommended)
Section titled “Using the getClientOptions Helper (Recommended)”import { getClientOptions } from "@azure-tools/typespec-client-generator-core";
// Get one client option from a modelconst sdkModel = context.sdkPackage.models.find((m) => m.name === "MyModel");const enableFeatureFoo = getClientOptions(sdkModel, "enableFeatureFoo");
if (enableFeatureFoo === true) { // Generate the feature supported by this emitter.}The function returns the option value as unknown, or undefined when the named option isn’t present. Narrow or validate the value before using it, then call it once for each option key your emitter supports.
Works with Any Decorated SDK Type
Section titled “Works with Any Decorated SDK Type”The helper works with any decorated SDK type:
// Modelsconst modelOption = getClientOptions(sdkModel, "enableFeatureFoo");
// Enumsconst enumOption = getClientOptions(sdkEnum, "enableFeatureFoo");
// Operations/Methodsconst methodOption = getClientOptions(sdkMethod, "enableFeatureFoo");
// Propertiesconst propertyOption = getClientOptions(sdkProperty, "enableFeatureFoo");
// Clientsconst clientOption = getClientOptions(sdkClient, "enableFeatureFoo");Alternative: Manual Decorator Filtering
Section titled “Alternative: Manual Decorator Filtering”If you need more control, you can also filter the decorators array directly:
const sdkModel = context.sdkPackage.models.find((m) => m.name === "MyModel");const clientOptionDecorators = sdkModel.decorators.filter( (d) => d.name === "Azure.ClientGenerator.Core.@clientOption",);
for (const decorator of clientOptionDecorators) { const optionName = decorator.arguments.name; // e.g., "enableFeatureFoo" const optionValue = decorator.arguments.value; // e.g., true const scope = decorator.arguments.scope; // e.g., "python"}Supported Client Options
Section titled “Supported Client Options”| Option Name | Value Type | Target | Languages | Description |
|---|---|---|---|---|
omitSlashFromEmptyRoute | boolean | Operation, Interface, Namespace | All | When true, operations with empty routes (path "/") will use "" instead. Only affects empty routes. |
#suppress "@azure-tools/typespec-client-generator-core/client-option" "legacy storage usage"@clientOption("omitSlashFromEmptyRoute", true, "python")@putop createBlob(): void;Best Practices
Section titled “Best Practices”-
Always specify a scope: The decorator is designed for language-specific behavior. Omitting the scope produces an additional warning.
-
Suppress the warning intentionally: Use
#suppress "@azure-tools/typespec-client-generator-core/client-option"to acknowledge that you’re using this advanced feature. -
Document usage: When using client options, document why they’re needed so future maintainers understand the intent.
-
Prefer standard decorators: Use standard TCGC decorators like
@clientName,@access,@usage, etc. when they can achieve the desired behavior. Reserve@clientOptionfor cases where no standard decorator exists. -
Coordinate with emitter teams: Before using a client option, verify with the target language emitter team that the option is supported and understand its behavior.