Skip to content

fix(typings): correct Client method emit; type the full API; infer implement args from define schemas#2

Open
Loner1536 wants to merge 2 commits into
KYRORBLX:mainfrom
Loner1536:typings-fixes-and-inference
Open

fix(typings): correct Client method emit; type the full API; infer implement args from define schemas#2
Loner1536 wants to merge 2 commits into
KYRORBLX:mainfrom
Loner1536:typings-fixes-and-inference

Conversation

@Loner1536

@Loner1536 Loner1536 commented Jul 6, 2026

Copy link
Copy Markdown

Types-only PR — no .luau changes and no runtime behavior changes. Rewrites typings/index.d.ts to match the Luau source and adds schema→callback inference for roblox-ts consumers.

Fix

  • Client methods emitted as dot calls. Controller's members are colon-methods (function Controller:show()), but the typings declared them as arrow properties, so roblox-ts emitted client.show() — no self — and every method on a Konsole.create() client failed at runtime from TS. Client now uses method signatures, and the top-level Api no longer extends it, since the top-level functions are dot-style in init.luau and must keep emitting Konsole.show().

Additions (all backward compatible)

  • Schema→callback inference. define captures the args schema and returns a Command whose .server is a branded string (ServerName<A>; plain string at runtime). Passing it to implement types the callback parameters automatically:

    const giveXp = Konsole.define({
        name: "giveXp",
        server: "giveXpServer",
        args: [
            { name: "target", type: "player", required: true },
            { name: "amount", type: "number", required: true },
        ],
    });
    
    Konsole.implement(giveXp.server, (context, player, amount) => {
        // player: Player, amount: number — no annotations or casts
    });

    implement("name", cb) with a plain string still works via overload.

  • Optional-arg truthfulness. required: false with no default types as | undefined, matching Arguments.parse (which skips such args); args with a default stay non-optional (defaults are inserted unconverted), and an absent required behaves as required.

  • Full API surface typed from source: Result (ok/err/table/status/fromRenderResult per result.luau), Ranks (incl. RankEntity = Player | userId and the built-in rank-name union), Dispatch, Kommand, Arguments (incl. the Arguments.types converter registry), Chat, Render, and every Config group so create() overrides autocomplete.

  • Editor completions inside args. define's type parameter now defaults to its constraint instead of [] — the empty-tuple default gave partially-typed arg objects a never contextual type, so editors showed no property completions.

Verification

  • Signatures traced module-by-module against src/ (dispatch, kommand, arguments, ranks, config, result, controller).
  • Typechecked in a roblox-ts project (TS 5.5), including tsserver completion probes and tuple-optionality assertions.
  • const type parameters require TS ≥ 5.0 (roblox-ts already requires newer).

Notes

  • host's implementations record uses Run<Array<any>>unknown[] would reject typed callbacks under contravariance.
  • ExecuteResult is Outcome | RenderResult; commands returning arbitrary tables still pass through at runtime.
  • Render.Formatter / Render.Text are left unknown (UI internals).

Disclosure

The main thing I wanted fixed was auto-typing for implement — in the upstream typings, define returns a plain Command with no arg capture, implement takes (name: string, callback: Run) where Run is (context, ...unknown[]), and all the sub-modules (Ranks, Dispatch, Context.dispatch, etc.) are typed unknown. So there was no inference at all: you'd define a command with a typed args schema and still have to manually annotate every callback parameter.

The upstream Client interface also has every member as an arrow property (dot-call style), but the Luau controller uses colon-methods, so all Konsole.create() client calls were emitting client.show() with no self and failing at runtime.

I didn't have time to audit the full typings rewrite myself, so I ran it through Claude (Fable 5), which traced each declaration against the Luau source module-by-module. I've reviewed the result and it's been tested in-game, but a second pair of eyes on the API surface wouldn't hurt.

🤖 Generated with Claude Code

…mplement args from define schemas

Fixes:
- Client members are colon-methods in Luau (Controller:show, etc.) but were
  typed as arrow properties, so roblox-ts emitted client.show() dot calls
  with no self. Client is now declared with method signatures, and the
  top-level Api (dot-functions in Luau) no longer extends it.
- commands.aliases config is a { [string]: string } map, was typed string[].

Additions (types only, no runtime changes):
- Konsole.define captures the args schema and returns a Command whose
  .server is a branded string; passing it to Konsole.implement types the
  callback parameters automatically (no casts or annotations needed).
  Plain-string implement(name, cb) still works via overload.
- required: false args with no default type as | undefined, matching
  Arguments.parse, which skips them; defaults are inserted unconverted.
- Typed Result (ok/err/table/status/from -> RenderResult), Ranks, Dispatch,
  Kommand, Arguments (incl. the converter registry), Chat, Render, and the
  full Config groups so create()/config overrides autocomplete.
- rank fields accept built-in rank names (player/helper/moderator/admin/
  creator + aliases) alongside numbers.
- define's type parameter defaults to its constraint instead of [] so
  editors show Argument property completions inside partially-typed args
  (an empty-tuple default left completions with a never contextual type).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dullflowerr dullflowerr self-assigned this Jul 6, 2026
@dullflowerr

Copy link
Copy Markdown
Member

after reviewing, please fix the RunArgs helper first. In a roblox-ts TS 5.5 test with @rbxts/types + @rbxts/compiler-types and skipLibCheck=false, typings/index.d.ts errors at RunArgs: Type '"length"' cannot be used to index type 'T', after that is fixed, i'm good with merging

@dullflowerr dullflowerr added bug Something isn't working invalid This doesn't seem right labels Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working invalid This doesn't seem right

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants