Data decorators#10197
Conversation
commit: |
|
All changed packages have been documented.
Show changes
|
|
You can try these changes here
|
|
I generally like the idea of the feature but I have a couple of reservations:
On the questions:
|
|
Design meeting descision:
|
|
Hi @@timotheeguerin. Your PR has had no update for 30 days and it is marked as a stale PR. If it is not updated within 30 days, the PR will automatically be closed. If you want to refresh the PR, please remove the |
Data Decorators
Summary
Adds a
datamodifier for decorator declarations. Data decorators are simple metadata annotations that auto-store their arguments — no JavaScript implementation needed.Motivation
A large number of decorators in the TypeSpec ecosystem follow the same pattern: accept arguments, store them in a state map, expose a getter. This requires boilerplate across three files (
.tspdeclaration,.tsimplementation,.tsstate accessors). Data decorators eliminate this entirely.Design
Syntax
datais a new modifier keyword ondecdeclarations, mutually exclusive withextern:Storage
The compiler auto-generates an implementation that stores args in
program.stateMapkeyed bySymbol.for("data-dec:<fqn>"):true{ paramName1: val1, paramName2: val2 }Compiler API
Generic functions to read data decorator state by FQN string — no generated code needed:
tspd generation
tspd gen-extern-signaturegenerates typed accessors for data decorators:Decorator type
The
Decoratorruntime type gains adeclarationKind: "extern" | "data"property (extensible for future kinds).dataas a contextual keyworddatais a modifier keyword but remains usable as an identifier (decorator names, property names, etc.) to avoid breaking existing code like@datain@typespec/events.Open Questions
Modifier name: Is
datathe right keyword? Alternatives considered:metadata,declare,attr,pure.datawas chosen for brevity and precedent (Kotlindata class), but open to alternatives.Multiple data decorators on the same node: Should multiple different data decorators be allowed on the same target? Currently there's no restriction — each stores independently. Should we add validation or a way to declare exclusivity?
Behavior with
model is/op is: When a model or operation copies from another viais, should data decorator metadata be inherited by the copy? Currently decorators applied viaisare re-applied, so data decorators would also be re-applied. Is this the desired behavior, or should data decorators have different inheritance semantics?Migration Examples
Several existing decorators across the TypeSpec ecosystem are pure "store args in state" and could be migrated to
data dec:Compiler —
@discriminatorBefore:
After:
No JS needed.
HTTP —
@body,@bodyRoot,@bodyIgnore,@statusCode,@multipartBodyThese are all boolean flags — the decorator just marks the target:
Before:
After:
Same pattern applies to
@bodyRoot,@bodyIgnore,@statusCode,@multipartBody.OpenAPI —
@operationIdBefore:
After:
Not candidates
Decorators that do validation, normalization, or side effects beyond storage are not candidates. Examples:
@doc(template string rewriting),@format(uniqueness validation),@pattern(regex validation),@route(shared route handling),@server(URL parameter parsing).