-
Notifications
You must be signed in to change notification settings - Fork 374
Description
What is the type of issue?
Documentation Improvement
What is the issue?
Issue Identified
The original documentation contained:
- Long and complex sentences, making it harder to read.
- Inconsistent terminology (e.g., "ElysiaJs" vs. "Elysia").
- Unclear explanations, especially around method chaining and controllers.
- Inconsistent code formatting, which could confuse developers.
Key Improvements
-
Grammar & Clarity
- Correct grammatical errors for better readability.
- Improve sentence structure for clearer explanations.
-
Consistency
- Use a uniform writing style (e.g., consistently referring to "ElysiaJs" or "Elysia").
- Standardize phrasing (e.g., "should" vs. "recommended").
-
Code Readability
- Maintain consistent formatting and indentation.
- Add concise comments where necessary for clarity.
Improved Version
Best Practices
Elysia is a pattern-agnostic framework, allowing developers to choose the coding patterns that best suit their needs.
However, implementing the MVC (Model-View-Controller) pattern in Elysia can be challenging due to difficulties in decoupling logic and handling types effectively.
This guide outlines best practices for structuring an Elysia application while maintaining flexibility in adopting other coding styles.
Method Chaining
Elysia code should always follow method chaining to maintain type integrity.
Since Elysia’s type system is dynamic, each method returns a new type reference. Using method chaining ensures proper type inference, preventing type-related issues.
✅ Recommended Approach (Method Chaining):
import { Elysia } from 'elysia'
new Elysia()
.state('build', 1)
// The store is strictly typed
.get('/', ({ store: { build } }) => build)
.listen(3000)
Here, .state('build', 1)
modifies the ElysiaInstance
type, ensuring build
is correctly inferred.
❌ Avoid This (No Method Chaining):
import { Elysia } from 'elysia'
const app = new Elysia()
app.state('build', 1) // Type information is lost
app.get('/', ({ store: { build } }) => build) // ❌ Property 'build' does not exist
app.listen(3000)
Why?
Without method chaining, Elysia does not retain new types, leading to incorrect type inference.
Controllers
One Elysia instance should act as one controller.
Passing an entire Context
object to a separate controller can cause issues:
- Increased complexity: Elysia’s types are dynamic and change based on plugins and method chaining.
- Typing difficulties: Elysia’s type system evolves with decorators and state.
- Inconsistent type casting: Manually casting types can break type consistency between definitions and runtime behavior.
❌ Avoid Using a Separate Controller Class:
import { Elysia, type Context } from 'elysia'
abstract class Controller {
static root(context: Context) {
return Service.doStuff(context.stuff)
}
}
// ❌ This adds unnecessary complexity
new Elysia()
.get('/', Controller.root)
Why?
Using a full controller method introduces an extra controller layer, which complicates type inference.
✅ Recommended Approach (Treat Elysia as the Controller):
import { Elysia } from 'elysia'
import { Service } from './service'
new Elysia()
.get('/', ({ stuff }) => Service.doStuff(stuff))
This approach maintains type safety, simplicity, and clarity.
Services
A service in Elysia is a set of utility/helper functions that separate business logic from the main controller.
Elysia supports two types of services:
- Non-request dependent services – Functions that do not require request properties.
- Request-dependent services – Functions that rely on request-specific data.
✅ Example of a Non-Request Dependent Service:
import { Elysia } from 'elysia'
abstract class Service {
static fibo(n: number): number {
return n < 2 ? n : Service.fibo(n - 1) + Service.fibo(n - 2)
}
}
new Elysia()
.get('/fibo', ({ body }) => Service.fibo(body), {
body: t.Numeric()
})
If a service does not need stored properties, using an abstract class with static methods prevents unnecessary instantiation.
Where did you find it?
These issues were found in the Elysia documentation, specifically in sections related to:
- Best Practices
- Method Chaining
- Controllers
- Services