Skip to content

Dispatch declaration overrides in Experimental_ComponentOverrides - #11597

Draft
Timothee Guerin (timotheeguerin) wants to merge 2 commits into
microsoft:mainfrom
timotheeguerin:ef/declaration-overrides
Draft

Dispatch declaration overrides in Experimental_ComponentOverrides#11597
Timothee Guerin (timotheeguerin) wants to merge 2 commits into
microsoft:mainfrom
timotheeguerin:ef/declaration-overrides

Conversation

@timotheeguerin

Copy link
Copy Markdown
Member

An override descriptor already accepted a declaration entry, but nothing ever dispatched to it — only reference was wired up. So an emitter could change how a type is referenced and had no say in how it is declared. The only way to customize a declaration was to copy the framework component into your own package and diverge from it, which is exactly what @typespec/http-server-csharp did for classes, properties and enums.

Experimental_OverridableComponent now dispatches declaration too, and the C# ClassDeclaration, Property and EnumDeclaration render through it. An override can replace the declaration outright, or re-render the default with different props:

const overrides = Experimental_ComponentOverridesConfig().forTypeKind("ModelProperty", {
  declaration: (props) =>
    isSecret(props.type) ? (
      <props.Declaration {...props.declarationProps} public={false} internal />
    ) : (
      props.default
    ),
});

props.Declaration is the unwrapped body, so re-rendering it does not recurse back through the override.

The declaration props type is generic and defaults to Record<string, any>, because the existing Experimental_CustomTypeToProps map is TypeScript-specific (VarDeclarationProps, ObjectPropertyProps) and means nothing for C#. Callers that want type safety pass the concrete props type: .forTypeKind<"ModelProperty", PropertyProps>(...).


Part of a 7-PR stack moving @typespec/http-server-csharp onto the emitter framework. Stacked on #11596 — only the last commit is new here.

Adds handling for Tuple, StringTemplate, EnumMember, ModelProperty, UnionVariant,
template parameters and the full Intrinsic set. An unsupported type now reports a
diagnostic and falls back to `object` instead of throwing.

Also fixes the C# components reporting a TypeScript diagnostic for unsupported
scalars, and corrects the C# expressions emitted for the `null` and `never`
intrinsics. Adds an `isCSharpValueType` util.
…al_ComponentOverrides

The `declaration` descriptor existed but nothing dispatched to it, so an emitter
could override how a type is referenced but not how it is declared. The C#
`ClassDeclaration`, `Property` and `EnumDeclaration` now render through the
override point.
@pkg-pr-new

pkg-pr-new Bot commented Aug 7, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/emitter-framework@11597

commit: e806960

@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter-framework Issues for the emitter framework label Aug 7, 2026
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @typespec/emitter-framework
Show changes

@typespec/emitter-framework - fix ✏️

Make the C# TypeExpression handle every type kind instead of throwing,> ,> Tuple, StringTemplate, EnumMember, ModelProperty, UnionVariant, template parameters and the full Intrinsic set are now supported, and an unsupported type reports a diagnostic and falls back to object rather than throwing. Also fixes the C# components reporting a TypeScript diagnostic for unsupported scalars, and corrects the C# expressions for the null and never intrinsics.

@typespec/emitter-framework - feature ✏️

Support declaration overrides in Experimental_ComponentOverrides,> ,> Only reference overrides were dispatched, so an emitter could customize how a type is referenced but not how it is declared, forcing it to fork the framework's declaration components. The C# ClassDeclaration, Property and EnumDeclaration now render through the override point.,> ,> tsx,> const overrides = Experimental_ComponentOverridesConfig().forTypeKind("ModelProperty", {,> declaration: (props) =>,> props.type.name === "id" ? (,> <props.Declaration {...props.declarationProps} name="Identifier" />,> ) : (,> props.default,> ),,> });,>

@azure-sdk-automation

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter-framework Issues for the emitter framework

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant