H
Hono•3mo ago
Benno

Enforcing strict types for Hono's c.json() responses?

Is it possible to enforce strict typing for Hono's c.json() responses at a top level (hono.Handler<..>)? Currently, I can define expected response types like this:
type MyResponse = {someType: string};
type MyHandlerResponse = hono.HandlerResponse<MyResponse>;
type MyHandler = hono.Handler<any, any, any, MyHandlerResponse>
type MyResponse = {someType: string};
type MyHandlerResponse = hono.HandlerResponse<MyResponse>;
type MyHandler = hono.Handler<any, any, any, MyHandlerResponse>
This provides suggestions in c.json({...}), but doesn't raise a type error for mismatched types:
c.json('') // No type error, even though it should be an object. I get suggestions though, see video
c.json('') // No type error, even though it should be an object. I get suggestions though, see video
Hono's internal types for quick reference:
export type HandlerResponse<O> = Response | TypedResponse<O> | Promise<Response | TypedResponse<O>>;

export type TypedResponse<T = unknown, U extends StatusCode = StatusCode, F extends ResponseFormat = T extends string ? 'text' : T extends JSONValue ? 'json' : ResponseFormat> = {
_data: T;
_status: U;
_format: F;
};
export type HandlerResponse<O> = Response | TypedResponse<O> | Promise<Response | TypedResponse<O>>;

export type TypedResponse<T = unknown, U extends StatusCode = StatusCode, F extends ResponseFormat = T extends string ? 'text' : T extends JSONValue ? 'json' : ResponseFormat> = {
_data: T;
_status: U;
_format: F;
};
Example: https://github.com/builder-group/community/blob/develop/examples/openapi-router/express/petstore/src/router.ts Code: https://github.com/builder-group/community/blob/develop/packages/openapi-router/src/types/features/hono.ts
GitHub
community/examples/openapi-router/express/petstore/src/router.ts at...
A collection of open source libraries by builder.group. Let's build together. - builder-group/community
GitHub
community/packages/openapi-router/src/types/features/hono.ts at dev...
A collection of open source libraries by builder.group. Let's build together. - builder-group/community
4 Replies
Benno
BennoOP•3mo ago
Thanks, will check it out 🙂
Benno
BennoOP•3mo ago
Does this also work on the hono.Handler level? Because it doesn't seem so. I get the type suggested by the IDE (see image) but not enforced, meaning that I don't get an error if its wrong. I guess its because of Response | TypedResponse<O> in the HandlerResponse?
export type TOpenApiHonoRequestHandler<GPath extends string, GPathOperation> = hono.Handler<
any,
TOpenApiToHonoUrlPattern<GPath>,
TOpenApiHonoInput<GPathOperation>,
TOpenApiHonoResponse<GPathOperation> // <-
>;

export type TOpenApiHonoResponse<GPathOperation> = hono.HandlerResponse<
// TOperationSuccessResponseContent<GPathOperation>
TResponse<{ hello: string }>
>;

interface TResponse<T> {
message: string;
data: T;
}
export type TOpenApiHonoRequestHandler<GPath extends string, GPathOperation> = hono.Handler<
any,
TOpenApiToHonoUrlPattern<GPath>,
TOpenApiHonoInput<GPathOperation>,
TOpenApiHonoResponse<GPathOperation> // <-
>;

export type TOpenApiHonoResponse<GPathOperation> = hono.HandlerResponse<
// TOperationSuccessResponseContent<GPathOperation>
TResponse<{ hello: string }>
>;

interface TResponse<T> {
message: string;
data: T;
}
Hono's internal types for quick reference:
export type HandlerResponse<O> = Response | TypedResponse<O> | Promise<Response | TypedResponse<O>>;

export type TypedResponse<T = unknown, U extends StatusCode = StatusCode, F extends ResponseFormat = T extends string ? 'text' : T extends JSONValue ? 'json' : ResponseFormat> = {
_data: T;
_status: U;
_format: F;
};
export type HandlerResponse<O> = Response | TypedResponse<O> | Promise<Response | TypedResponse<O>>;

export type TypedResponse<T = unknown, U extends StatusCode = StatusCode, F extends ResponseFormat = T extends string ? 'text' : T extends JSONValue ? 'json' : ResponseFormat> = {
_data: T;
_status: U;
_format: F;
};
No description
Benno
BennoOP•3mo ago
Wait I can just directly pass the hono.TypedResponse instead of going through the hono.HandlerResponse. Now its working. Not perfect since the type gets enforced on the handler level (not at c.json) but better than before. Thanks for the hint 🙂
export type TOpenApiHonoResponse<GPathOperation> = hono.TypedResponse<
TOperationSuccessResponseContent<GPathOperation>
>;
export type TOpenApiHonoResponse<GPathOperation> = hono.TypedResponse<
TOperationSuccessResponseContent<GPathOperation>
>;
Want results from more Discord servers?
Add your server