| layout | default |
|---|---|
| title | Namespaces |
| parent | Architecture |
| nav_order | 3 |
| permalink | /architecture/namespaces/ |
PineTS mimics Pine Script's namespacing (ta., math., request.) through modular namespace classes attached to the Context.
Every function in a namespace is implemented using a factory pattern:
// Factory receives the Context
export function myFunc(context: any) {
// Returns the actual function to be called by user code
return (arg1, arg2, _callId) => {
// Logic accessing context...
};
}Each namespace implements its own param() function. This is the interface between the transpiler and the runtime.
- Input: Raw value, Array, or Series.
- Output:
Seriesobject (usually), or raw value (forarraynamespace).
ta/math: Need to operate on Series. They wrap scalars in Series so.get(0)works universally.array: Operates on Pine Array Objects.param()returns the raw object/value, not a Series wrapper.request: Handles Tuples and needs the Parameter ID for caching secondary contexts.
In Pine Script, namespace members can be accessed without parentheses:
// Pine Script - property-like access
tr1 = ta.tr // No parentheses
tr2 = ta.tr(true) // With parameter
pi = math.pi // Constant access
PineTS simplifies this by implementing everything as methods. The transpiler automatically converts property access to method calls. This eliminates the complexity of maintaining separate getters and methods.
- Implementation: All namespace members are implemented as methods (even constants):
// Indicator with optional parameter
export function tr(context: any) {
return (handle_na?: any) => {
const handleNa = handle_na !== undefined ? Series.from(handle_na).get(0) : true;
// ... calculation logic
};
}
// Constant (zero-parameter method)
export function pi(context: any) {
return () => Math.PI;
}- Transpiler Transformation: When the transpiler encounters namespace member access without parentheses, it automatically adds them:
// User writes:
const tr = ta.tr;
const pi = math.pi;
// Transpiler converts to:
const tr = ta.tr();
const pi = math.pi();- Explicit Calls: Methods called with parentheses work normally:
// User writes:
const tr = ta.tr(true);
// Transpiler passes through (with parameter wrapping):
const tr = ta.tr(ta.param(true, undefined, 'p0'), '_ta0');The transformation applies to direct namespace access for known Pine Script namespaces (ta, math, request, array, input):
// ✅ Transformed: Direct namespace access (all members)
ta.tr → ta.tr()
ta.ema → ta.ema()
math.pi → math.pi()
math.abs → math.abs()
// ✅ Not transformed: Already a call
ta.tr() → ta.tr()
ta.tr(true) → ta.tr(true)
// ✅ Not transformed: Variable assignment
const myTa = context.ta;
myTa.tr → myTa.tr (no transformation)- Simplicity: Single implementation pattern for all namespace members
- No Special Cases: No need to distinguish between "getters" and "methods"
- Consistency: All namespace functions follow the same factory pattern
- Flexibility: Easy to add optional parameters to any function
- Maintainability: Less code, fewer edge cases to handle
- Performance: No overhead from property getters or descriptor lookups
All namespace members work the same way:
// Indicators with optional parameters
const tr1 = ta.tr; // Auto-converted to ta.tr()
const tr2 = ta.tr(true); // With parameter
// Indicators with required parameters
const ema = ta.ema; // Auto-converted to ta.ema() (transpiler adds params)
const ema2 = ta.ema(close, 14); // With explicit parameters
// Constants (zero-parameter methods)
const pi = math.pi; // Auto-converted to math.pi()
const e = math.e; // Auto-converted to math.e()Prior to this approach, PineTS used JavaScript getters for some namespace members. This created unnecessary complexity:
- ❌ Two different patterns to maintain (getters vs methods)
- ❌ Getters couldn't accept optional parameters
- ❌ Required special handling in the namespace class
- ❌ More complex barrel file generation
The unified method approach solves all of these issues by treating everything the same way.
For implementation details of specific namespaces, see their source READMEs: