Hono is not type-safe (yet)…

Kevin Firko
Published:

Hono is one of the hottest back-end API frameworks in the TypeScript ecosystem right now.

It bills itself as fast, lightweight, [and] built on Web Standards and it boasts support for any JavaScript runtime. Overall I think that it’s an excellent framework with a bright future.

Nearly everything I’ve read or watched about Hono describes it as “type safe”…

Hono is not type-safe. At least not yet. I’ll explain why in this post.

Versions

This post is current as of the Hono release v4.4.12 at the time of writing: 2024-07-10.

The official middleware versions are:

  • @hono/zod-validator v0.2.2
  • @hono/valibot-validator v0.3.0

It’s important to remember that in many respects Hono is still a work in progress that’s advancing per a philosophy to be fast and only depend on Web Standard API’s. Type safety is more of a goal than an achieved milestone.

Consider that the major version number of the @hono packages I am writing about is v0.

Why Hono Isn’t Type Safe… (Yet)

Design Decisions

A portion of Hono’s growing popularity can be explained by the familiar experience it offers to developers who have worked with leading predecessors like Express.

I recall when I tried Hono for the first time it felt like I already knew Hono.

While the design decision to feel familiar empowers many it also comes at a cost to the framework: it can be challenging for maintainers to properly type some of the patterns that were popular during the wild-west era of untyped JS.

It’s absolutely possible to write similar API’s that are more strictly defined that would be easier to type and have numerous other benefits however Hono made its design choices and who am I to argue with its popularity.

Escape Hatches

How does Hono provide type safety in the tricky parts?

It cheats.

If you use search the codebase of honojs/hono or honojs/middleware on GitHub you can find plenty of escape hatches like @ts-ignore, @ts-expect-error, and any.

Some escape hatches are understandable and in some cases they’re absolutely necessary.

However it appears there are many cases where escape hatches are used to work around real type issues instead of fixing the core problem and therefore they contribute to an illusion of type safety.

Escape hatches should always be employed with extreme caution because they effectively disable type checking and nullify the point of using TypeScript in the first place.

I always advocate that every escape hatch in a professional TS codebase be documented with a clear explanatory comment and that the usage is reviewed by developers who can tell the difference.

A great eslint rule is @typescript-eslint/ban-ts-comment which can be configured with the option allow-with-description.

Escape Hatches in Validation Code

It’s not ideal to find “type cheats” in code whose sole purpose is to provide type-safety and offer assurances about data at run-time.

Let’s inspect the official middleware packages @hono/zod-validator and @hono/valibot-validator.

zod and valibot are popular libraries that offer the potential to deliver type-safety enforced via run-time validation. Each has a corresponding @hono package that integrates them into the framework for validating requests.

In both integrations we find the same line in a crucial spot:

// @ts-expect-error not typed well
validator(target, async (value, c) => {
  // ...
})

Doh! The same framework that hype-driven novelty-seeking “tech influencers” are breathlessly calling “type safe” is “not typed well” per comments in its own codebase!

References:

I appreciate the professionalism of the maintainers and for explaining this escape hatch with a telling comment. They’re working on creating something wonderful vs. spreading noise as tech influencers.

If you take a look at the types the maintainers were struggling with you’ll see that they are indeed a doozy.

Type Issues in Practice

I found that it is unlikely for a developer to encounter a type issue so long as one creates a Hono API based on the docs and provided examples i.e. the “happy path”.

This enables the combination of type definitions and type cheats work out in a way that was anticipated by the maintainers.

The situation changes if you try to create type-safe generic helper functions or utilities related to Hono middleware.

I encountered issues because I like to “flex” any new-to-me framework with relevant experiments before I commit to it for a project.

I hit inexplicable type issues when I tried writing type-safe generic helper functions and middleware utilities to streamline working with slonik, a respected and truly type-safe library for working with Postgres + zod.

I found that I couldn’t figure out how Hono’s types actually worked or fit together when I drilled into them using VSCode.

Ultimately this led me to inspect Hono’s codebase where I realized it’s because the types don’t actually fit together and that’s what inspired this post.

Conclusions

Impact of Compromised Type Safety

TypeScript’s type system is only ever as strong as the weakest link.

Once a type-related “chain of trust” is broken through misuse of an escape hatch then any depdendent types downstream from that point on become suspect.

This means that many parts of Hono’s growing codebase carry the risk of presenting developers with confusing or misleading types.

Examples include the framework’s solutions for supporting OpenAPI (swagger) to its much-venerated RPC client feature.

If the root causes are not addressed then it stands to reason that the number of risky escape hatches will only grow.

Misuse of escape hatches have a nasty way of proliferating downstream; I sometimes describe them as “infectious”.

Type issues can also potentially contribute to security issues. For example a developer could feasibly leak secrets in a case where the type system erroneously indicated that confidential data fields aren’t present in a response object when they actually are.

Working with the Status Quo

At the end of the day I like Hono and I really appreciate its unique strengths. I am very interested in watching related projects like honox develop further.

My hope is that calling out type its issues will attract attention and resources that lead to improvements.

At least for now sticking to the “happy paths” per the docs and examples will just work even if there’s some “magic” at play behind the curtain.

I hope the day comes soon when Hono delivers true type safety through a rigorous “chain of trust” (in the type sense) that spans end-to-end.