Skip to content

RFC: total effect signatures — every effect in the header #14

@marcelofarias

Description

@marcelofarias

The bot-specific problem

Reviewing a 30-file bot PR is impossible if you have to read every body to know what each function does. TypeScript signatures lie by omission: a function typed (x: string) => string can hit the network, mutate globals, and read env vars.

Proposal

Extend uses { net } so every effect, mutation, and external dependency is part of the signature. No escape hatches: any is banned, untyped imports are banned, hidden globals are banned. A reviewer can audit a function from its header alone.

fn loadUser(id: string)
  uses   { net, time }
  reads  { cache }
  writes { metrics }
  throws { HttpError, TimeoutError }
  -> Result<User, string> { ... }

What the compiler does

  • Effect inference pass; if the body uses an effect not declared, compile error
  • Bans any, as unknown, untyped imports, untyped require, globalThis access
  • Effects are part of the type — a function expecting (x) => Result<T> with no effects rejects a body that hits the net

Why it's killer for bots

  • Reviewer reads headers, trusts the body. Scales to bot-volume PRs.
  • Bots can't lie about side effects, even by accident.

Open questions

  • How granular do effect kinds get? net.http? net.dns? Or just net?
  • Inferred vs. declared: does the compiler infer and require declaration, or just check the declaration?
  • Interop with untyped npm packages — wrapper modules with declared effects?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bot:implImplementation in progress or completeddiscussionDesign discussion or RFCenhancementNew feature or requestquestionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions