Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass a string field to c.json throws Type instantiation is excessively deep and possibly infinite.ts(2589) #3494

Closed
kaio-eduardo opened this issue Oct 6, 2024 · 14 comments

Comments

@kaio-eduardo
Copy link

What version of Hono are you using?

4.6.3

What runtime/platform is your app running on?

Node

What steps can reproduce the bug?

  1. Return a c.json with a string field
  2. Let it empty or add a . or /

What is the expected behavior?

No typescript errors

What do you see instead?

screen 2024-10-06 181643

Type instantiation is excessively deep and possibly infinite.ts(2589)

Additional information

If you add another character this error does not happen or if you delete the period.

typescript: ^5.6.2

@safwanyp
Copy link

safwanyp commented Oct 7, 2024

This seems to be due to the complex computed types in src/utils/types.ts. I would imagine that breaking these down into smaller definitions will help (based on this issue).

Something like this maybe? Happy to create a PR if this looks good maintainers.

// Intermediate types to simplify JSONParsed
type ToJSON<T> = T extends { toJSON(): infer J } ? J : never
type HandleInvalidJSON<T> = T extends InvalidJSONValue ? never : T
type HandleArray<T> = T extends ReadonlyArray<unknown>
  ? { [K in keyof T]: JSONParsed<InvalidToNull<T[K]>> }
  : T
type HandleSetMap<T> = T extends Set<unknown> | Map<unknown, unknown> ? {} : T
type HandleObject<T> = T extends object
  ? {
      [K in keyof OmitSymbolKeys<T> as IsInvalid<T[K]> extends true
        ? never
        : K]: boolean extends IsInvalid<T[K]> ? JSONParsed<T[K]> | undefined : JSONParsed<T[K]>
    }
  : T

// Simplified JSONParsed type
export type JSONParsed<T> = T extends JSONPrimitive
  ? T
  : ToJSON<T> extends never
  ? HandleInvalidJSON<HandleArray<HandleSetMap<HandleObject<T>>>>
  : JSONParsed<ToJSON<T>>

@yusukebe
Copy link
Member

Hi @kaio-eduardo

I can't reproduce it. Can you provide a minimal project to reproduce it?

@scarf005
Copy link

scarf005 commented Dec 3, 2024

@yusukebe it can be reproduced by passing unknown to c.json

minimal reproduction:

image
import { Hono } from "jsr:@hono/hono@^4.6.11"

new Hono().get("/", (c) => c.json({} as unknown))
jsr:@hono/hono@^4.6.11
deno 2.1.2 (stable, release, aarch64-apple-darwin)
v8 13.0.245.12-rusty
typescript 5.6.2

@yusukebe
Copy link
Member

yusukebe commented Dec 3, 2024

@scarf005

Why do you need to add unknown? I can't help you if you want to add unknown.

@scarf005
Copy link

scarf005 commented Dec 3, 2024

Why do you need to add unknown? I can't help you if you want to add unknown.

I want to return JSON file and not have type is excessively deep errors.

@yusukebe
Copy link
Member

yusukebe commented Dec 3, 2024

@scarf005

Sorry. I can't understand it. If you want our help, please provide a minimal project to reproduce it and show an interaction.

@scarf005
Copy link

scarf005 commented Dec 3, 2024

Sorry. I can't understand it. If you want our help, please provide a minimal project to reproduce it and show an interaction.

import { Hono } from "jsr:@hono/hono@^4.6.11"

new Hono().get("/", async (c) => c.json(JSON.parse(await Deno.readTextFile("file.json")) as unknown))

sorry, i don't understand which part you don't understand. could you elaborate?

@yusukebe
Copy link
Member

yusukebe commented Dec 3, 2024

@scarf005

You can't use unknown. To prevent the type error, please use as any.

@ghaaj
Copy link

ghaaj commented Dec 11, 2024

The same error occurs when trying to reference ReturnType of c.json.
reproduction: https://stackblitz.com/edit/github-a8gzkzvs

import { serve } from '@hono/node-server';
import { Hono, type Context } from 'hono';
import { createMiddleware } from 'hono/factory';

interface Env {
  Variables: {
    echo: (data: string) => ReturnType<Context['json']>;
    //                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    //                      Type instantiation is excessively deep and possibly infinite.(2589)
  };
}

const echoMiddleware = createMiddleware<Env>(async (c, next) => {
  c.set('echo', (data) => c.json({ data }));
  await next();
});

const app = new Hono();

app.get('/', echoMiddleware, (c) => {
  return c.var.echo('Hello Hono!');
});

const port = 3000;
console.log(`Server is running on http://localhost:${port}`);

serve({
  fetch: app.fetch,
  port,
});

@EdamAme-x
Copy link
Contributor

EdamAme-x commented Dec 12, 2024

Hi @ghaaj
You can use this

interface Env {
  Variables: {
    echo: (data: string) => Response;
  };
}

Playground

The reason for that error, c.json contains the types of Variables

@yusukebe yusukebe added not bug and removed triage labels Dec 12, 2024
@ghaaj
Copy link

ghaaj commented Dec 12, 2024

@EdamAme-x
Thank you! I'm thinking of using Response & TypedResponse<...> for more type safety.
I am sorry for the extra notifications.

@EdamAme-x
Copy link
Contributor

Hmmm, I don't think that way would change the type safety.

Copy link

This issue has been marked as stale due to inactivity.

@github-actions github-actions bot added the stale label Dec 20, 2024
Copy link

Closing this issue due to inactivity.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Dec 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants