Skip to content

Conversation

lCarvas
Copy link

@lCarvas lCarvas commented Aug 8, 2025

Summary

Currently TreatyResponse only considers the status code 200 as a success. All other 2xx status codes are shown under the error object. When returning status codes other than 200, hovering on data will show the type as unknown, hovering over error shows the returned status code under the error object.

export type TreatyResponse<Res extends Record<number, unknown>> =
        | {
              data: Res[200] extends {
                  [ELYSIA_FORM_DATA]: infer Data
              }
                  ? Data
                  : Res[200]
              error: null
              response: Response
              status: number
              headers: RequestInit['headers']
          }
        | {
              data: null
              error: Exclude<keyof Res, 200> extends never
                  ? {
                        status: unknown
                        value: unknown
                    }
                  : {
                        [Status in keyof Res]: {
                            status: Status
                            value: Res[Status] extends {
                                [ELYSIA_FORM_DATA]: infer Data
                            }
                                ? Data
                                : Res[Status]
                        }
                    }[Exclude<keyof Res, 200>]

This can be reproduced with the example below.

import { treaty } from "@elysiajs/eden";
import { Elysia } from "elysia";

const app = new Elysia()
  .get("/", ({ status }) => status(201))
  .listen(3000);

type App = typeof app

const api = treaty<typeof app>("localhost:3000")

const { data, error } = await api.get()

Solution

type SingleDigit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;

type SuccessKeys<R extends Record<number, unknown>> = {
  [K in keyof R]: K extends number
    ? `${K}` extends `2${SingleDigit}${SingleDigit}`
      ? K
      : never
    : never;
}[keyof R];

export type TreatyResponse<Res extends Record<number, unknown>> =
  | {
      data: Res[SuccessKeys<Res>] extends {
        [ELYSIA_FORM_DATA]: infer Data;
      }
        ? Data
        : Res[SuccessKeys<Res>];
      error: null;
      response: Response;
      status: number;
      headers: RequestInit["headers"];
    }
  | {
      data: null;
      error: Exclude<keyof Res, SuccessKeys<Res>> extends never
        ? {
            status: unknown;
            value: unknown;
          }
        : {
            [Status in keyof Res]: {
              status: Status;
              value: Res[Status] extends {
                [ELYSIA_FORM_DATA]: infer Data;
              }
                ? Data
                : Res[Status];
            };
          }[Exclude<keyof Res, SuccessKeys<Res>>];
      response: Response;
      status: number;
      headers: RequestInit["headers"];
    };

fixes: #199

Summary by CodeRabbit

  • New Features

    • Improved response handling to support all 2xx HTTP status codes, not just 200, for success responses.
  • Refactor

    • Generalized success and error response typing for broader compatibility with various HTTP status codes.

Copy link

coderabbitai bot commented Aug 8, 2025

Walkthrough

The changes introduce a new type alias to represent single digits and a conditional mapped type to extract all 2xx HTTP status code keys from a numeric record. The TreatyResponse type is updated to use these generalized success keys, allowing any 2xx status code to be treated as a success, not just 200.

Changes

Cohort / File(s) Change Summary
Type Generalization for HTTP Success Codes
src/treaty2/types.ts
Added SingleDigit type alias; introduced SuccessKeys mapped type for 2xx codes; updated TreatyResponse to generalize success and error typing based on 2xx status codes instead of just 200.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Treaty
    participant ResponseType

    Client->>Treaty: Make request
    Treaty->>ResponseType: Map response codes (Res)
    alt Response code is 2xx
        ResponseType-->>Client: data = Res[2xx]
    else Response code is not 2xx
        ResponseType-->>Client: error = Res[non-2xx]
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Assessment against linked issues

Objective Addressed Explanation
Generalize success inference to all 2xx codes, not just 200 (#199)
Ensure 201 and other 2xx codes are treated as success, not error (#199)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Poem

A hop and a skip, a type hops anew,
Now all 2xx codes bring successes through!
No more will 201 be lost in error's den—
For Treaty now knows, success is more than 200, my friend.
🐇✨

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b0519b and 300e046.

📒 Files selected for processing (1)
  • src/treaty2/types.ts (2 hunks)
🔇 Additional comments (4)
src/treaty2/types.ts (4)

160-160: LGTM!

The SingleDigit type correctly represents all digits 0-9 and is appropriately scoped within the Treaty namespace.


162-169: Excellent implementation of 2xx status code detection.

The SuccessKeys type uses a well-designed mapped conditional type with template literal matching to correctly identify all HTTP status codes in the 200-299 range. The logic is sound:

  1. Iterates over all keys in the response record
  2. Filters for numeric keys only
  3. Uses template literal type matching to check for the 2xx pattern
  4. Returns the union of all matching keys

This addresses the core issue described in the PR objectives.


173-177: Perfect generalization of success response typing.

The change from hardcoded Res[200] to Res[SuccessKeys<Res>] correctly allows the data property to be typed based on any 2xx status code response. This ensures that successful responses with status codes like 201, 202, etc., will be properly typed as data rather than errors.

The ELYSIA_FORM_DATA handling is correctly preserved in both conditional branches.


185-199: Correctly excludes all 2xx status codes from error handling.

The changes from Exclude<keyof Res, 200> to Exclude<keyof Res, SuccessKeys<Res>> perfectly complement the success response updates. Now all 2xx status codes are excluded from error handling, ensuring that:

  1. Status codes like 201, 202, etc., will no longer appear in the error object
  2. Only non-2xx status codes (4xx, 5xx, etc.) will be treated as errors
  3. The mapped type correctly processes the excluded error keys

This completes the fix for the issue described in #199 where successful status codes above 200 were incorrectly inferred as errors.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Successful status code above 200 get inferred to error
1 participant