Replies: 1 comment
-
there is a few things we want to make sure we do before we'd move forward with this. We did have the vision that this decorator syntax would be used for some more complex decorator implementation at some point(Without having to write the js implementation). So while supporting a subset of that as your proposal define sounds like a good initial step we do want to be sure it will be compatible with that potential future syntax and not back ourself into a corner. On thing I am thinking for example might be more appropriate is something of the sort dec uniqueId(target: ModelProperty, entityType: string) {
@@key(target);
@@format(target, "hex");
@@pattern(target, "^[a-f0-9]{64}$");
@@description(target, `A unique identifier for a ${entityType}.`);
} (using the augment decorator syntax to be explicit about what you target I think this answer a few of the questions above as well as yoiu can see this as basically jsut an implementation of the decorator and isn't to be treated much differently from the outside as if it was implemented in JS. This means it wouldn't really apply the |
Beta Was this translation helpful? Give feedback.
-
Problem Statement
TypeSpec users currently face challenges when they need to apply the same combination of decorators to multiple entities. This leads to repetitive code, which is harder to maintain and more error-prone. This issue was raised in TypeSpec discussion #1850.
Consider this example:
Repetition like this creates several challenges:
While custom scalars can help reduce some duplication, they don't provide a complete solution, particularly when:
Model inheritance and spread operators have similar limitations, as they don't allow for property name customization and may introduce unwanted inheritance semantics.
The decorator composition feature directly addresses these pain points by providing a mechanism for defining, parameterizing, and reusing decorator combinations without these limitations, aligning with TypeSpec's goals of creating clear, maintainable API definitions.
Proposed Solution: Decorator Compositions
We propose adding decorator composition to TypeSpec, allowing developers to define reusable decorator groups that can be parameterized. This is similar to how decorators themselves are defined in TypeSpec, but instead of implementing a single decorator function, a composition would expand to multiple decorators.
Syntax: Decorator Composition Definition
Syntax: Decorator Composition Usage
Decorator Composition Semantics
Expansion and Application
Decorator compositions are expanded at compile time, effectively inlining the constituent decorators. When a composition is applied, it's as if each decorator within the composition was applied individually in the order defined.
Type Checking and Parameters
Parameters to decorator compositions are type-checked according to their declared types. These parameters can be used in the composed decorators through string interpolation or direct reference:
Documentation Propagation
Documentation for decorator compositions works on two levels:
@doc
or@description
decorators within the composition are applied to the targetWhen a decorator composition is expanded, its documentation isn't directly propagated, but any documentation decorators within it are applied normally. This allows for targeted, contextual documentation.
Metadata and Emitter Interaction
Emitters interact with the expanded form of decorator compositions. By the time an emitter processes the TypeSpec program, compositions have been expanded to their constituent decorators. This ensures that emitters don't need special handling for compositions.
However, for debugging and tooling purposes, the compiler maintains references to the original composition in the program's metadata, allowing tools to show that a set of decorators came from a composition.
Benefits
Comparison with Similar Concepts in Other Languages
The concept of decorator compositions is analogous to several patterns in other programming languages:
Attribute Compositions in C#: C# allows defining custom attributes that combine the functionality of other attributes.
Example: ValidationAttributes
Java Annotation Grouping: Java allows defining meta-annotations that group multiple annotations together.
Example: Spring's composed annotations
Rust Attribute Macros: Rust allows creating attribute-like macros that expand to multiple attributes.
Example: Derive macros
Python Decorator Factories: Python allows creating functions that return combinations of decorators.
Example: Stacked decorators
TypeScript Decorators: TypeScript's experimental decorators allow for decorator factories that can apply multiple behaviors.
Example: Decorator Composition
Each of these approaches demonstrates how other languages have solved the problem of decorator composition. TypeSpec's proposal aims to provide a similarly elegant solution while maintaining the language's focus on type safety and clarity.
What sets this proposal apart is that it's fully integrated into TypeSpec's type system, ensuring that compositions are type-checked at compile time rather than being simple textual macros.
Comparison with Current Workarounds
Custom Scalars
Current workaround using custom scalars:
Issues with this approach:
Model Inheritance/Spread
Current workaround using inheritance:
Issues with this approach:
Advanced Examples
Authentication Requirements
Standard Response Codes
Conditional Use Cases without Non-Standard Syntax
While we should avoid introducing new syntax constructs for conditional decoration, the same patterns can be achieved by creating specific composition variants:
Technical Details
Next Steps
Questions for Discussion
Q: How should compositions interact with TypeSpec's type system?
Q: How should composition naming and namespaces be handled?
Q: Should we support composition nesting and extension?
Q: How should we handle composition recursion and safety?
Q: How should compositions interact with decorator targets?
Q: How should diagnostic messages and error reporting work with compositions?
Q: What are the compiler and performance implications?
Q: How should IDE and tooling support compositions?
Q: How should documentation generation handle compositions?
Q: What constraints should apply to decorator compositions?
Beta Was this translation helpful? Give feedback.
All reactions