Skip to content

Proposal: Idiomatic dependency access via this.method() (Memoized) #8

Description

@Lucifier129

Is your feature request related to a problem? Please describe.
Currently, accessing sibling tasks requires the specific this.$.key syntax. While functional, this "magic" $ property feels a bit non-standard and less intuitive than calling a method directly on the context.

Describe the solution you'd like
I propose optimizing the API to support direct method calls (e.g., await this.user()) to access dependencies.

Under the hood, these methods should be memoized. This ensures that even if this.user() is called multiple times (by the main runner or other dependent tasks), the underlying fetchUser logic is executed only once, and the same Promise is shared.

Example

Current syntax:

const { user, config, profile } = await all({
  async user() { return fetchUser() },
  async config() { return fetchConfig() },
  async profile() {
    // Requires .$ to access the task
    return fetchProfile((await this.$.user).id)
  }
})

Proposed syntax (More idiomatic):

const { user, config, profile } = await all({
  async user() { return fetchUser() },
  async config() { return fetchConfig() },
  async profile() {
    // Direct method call, automatically memoized
    const user = await this.user()     
    return fetchProfile(user.id)
  },
})

Proof of Concept
I have implemented a prototype demonstrating that this is achievable with perfect TypeScript inference (using ThisType without circular reference issues) and correct runtime behavior.

Demo: TypeScript Playground

This approach makes the code look more like standard class methods or closure patterns, improving readability and developer experience (DX).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions