H
Hono2mo ago
dan—1106

Inferring the response type of a handler

I'm trying to infer the return type of a route on my server. Any tips on what I'm doing wrong?
import type { Env } from "@/types";
import { createFactory } from "hono/factory";
import { InferResponseType } from "hono";

const factory = createFactory<Env>();

export const helloWorld = factory.createHandlers(async (c) => {
return c.json({
message: "Hello World",
});
});

type Route = typeof helloWorld[0]
type RouteResponse = Awaited<ReturnType<Route>>;
type Foo = InferResponseType<RouteResponse, 200>
import type { Env } from "@/types";
import { createFactory } from "hono/factory";
import { InferResponseType } from "hono";

const factory = createFactory<Env>();

export const helloWorld = factory.createHandlers(async (c) => {
return c.json({
message: "Hello World",
});
});

type Route = typeof helloWorld[0]
type RouteResponse = Awaited<ReturnType<Route>>;
type Foo = InferResponseType<RouteResponse, 200>
The route response type is
type RouteResponse = void | Response | (Response & TypedResponse<{
message: string;
}, ContentfulStatusCode, "json">)
type RouteResponse = void | Response | (Response & TypedResponse<{
message: string;
}, ContentfulStatusCode, "json">)
Foo is
type Foo = never
type Foo = never
any tips on what I'm doing wrong? I'm trying to get back something along the lines of { message: string; }
7 Replies
Weespies
Weespies2mo ago
I think you need to use the infertype directly on the handler from the examples I've seen previously I think its type foo = InferResponseType<typeof hellworld[0], 200>
dan—1106
dan—1106OP2mo ago
thanks!
export const helloWorld = factory.createHandlers(async (c) => {
return c.json({
message: "Hello World",
});
});

type foo = InferResponseType<typeof helloWorld[0], 200>
export const helloWorld = factory.createHandlers(async (c) => {
return c.json({
message: "Hello World",
});
});

type foo = InferResponseType<typeof helloWorld[0], 200>
also gives
type Foo = never
type Foo = never
as does
export const helloWorld = async (c: AppContext) => {
return c.json({
message: "Hello World",
});
};

type foo = InferResponseType<typeof helloWorld, 200>
export const helloWorld = async (c: AppContext) => {
return c.json({
message: "Hello World",
});
};

type foo = InferResponseType<typeof helloWorld, 200>
ambergristle
ambergristle2mo ago
InferResponseType is meant to be used with the RPC client, not the endpoints themselves i don't know if there's a good way to achieve what you're asking without getting into some gnarly typing @dan—1106 what's your goal here?
dan—1106
dan—1106OP2mo ago
I'm using Hono as the backend for a Stripe App I'm developing. Because of the way that Stripe Apps are sandboxed and I need to handle custom headers I don't think I can use the RPC client on the front end. I tried to use the hc object just for typing, but it returns typed as any
import type { AppType } from "@worker/index";
import { hc } from "hono/client";
const hcClient = hc<AppType>("");
import type { AppType } from "@worker/index";
import { hc } from "hono/client";
const hcClient = hc<AppType>("");
Sounds like getting this to work might be a more fruitful approach?
ambergristle
ambergristle2mo ago
depends on what your goals and priorities are there are a variety of ways to keep a client in sync with a handler's return type your app type probably isn't making it over the monorepo boundary because it's not generated. try emitting types w/o transpiling (i assume you're using a CF worker), and use those but i would probably statically type the handler and share that with the client instead * though this won't work so well with createHandlers. why are you using that?
dan—1106
dan—1106OP2mo ago
I saw the comment in the docs that the factory helpers facilitate setting the proper TypeScript types, and given that was part of my goals I was incorporating them! When should createHandlers be used?
ambergristle
ambergristle2mo ago
tbh, i haven't come across a really compelling use-case maybe if you wanted to package a series of middleware to make them more portable? using the factory helpers can make it easier to share types, but it's sort of niche. there are usually simpler ways to do that, depending on your use-case

Did you find this page helpful?