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

fix(type): degradation of generic type handling #3138

Merged

Conversation

m-shaka
Copy link
Contributor

@m-shaka m-shaka commented Jul 14, 2024

The author should do the following, if applicable

fix #3135

This works in the use case of the reported issue, I'm not 100% sure why this works though

  • Add tests
  • Run tests
  • bun run format:fix && bun run lint:fix to format the code
  • Add TSDoc/JSDoc to document the code

Copy link

codecov bot commented Jul 14, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 95.87%. Comparing base (2d01359) to head (4d9f716).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3138   +/-   ##
=======================================
  Coverage   95.87%   95.87%           
=======================================
  Files         137      137           
  Lines       13514    13514           
  Branches     2300     2285   -15     
=======================================
  Hits        12956    12956           
  Misses        558      558           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@m-shaka m-shaka changed the title fix: degration of generic type handling fix: degradation of generic type handling Jul 14, 2024
@m-shaka m-shaka force-pushed the fix-degration-of-generic-type-handling branch from d348b9e to c0f6aed Compare July 14, 2024 05:19
@@ -26,7 +26,9 @@ export type IfAnyThenEmptyObject<T> = 0 extends 1 & T ? {} : T

export type JSONPrimitive = string | boolean | number | null
export type JSONArray = (JSONPrimitive | JSONObject | JSONArray)[]
export type JSONObject = { [key: string]: JSONPrimitive | JSONArray | JSONObject | object }
export type JSONObject = {
[key: string]: JSONPrimitive | JSONArray | JSONObject | object | InvalidJSONValue
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A quick question. Is adding InvalidJSONValue to JSONObject our ideal definition? I feel it's weird JSONObject has InvalidJSONValue.

Copy link
Contributor Author

@m-shaka m-shaka Jul 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. That depends on the meaning of JSONValue.

For example, the first parameter of Context.json can be an object with a key whose value is InvalidJSONValue type, which has no problem

hono/src/context.ts

Lines 723 to 727 in bb14b1e

json: JSONRespond = <
T extends JSONValue | SimplifyDeepArray<unknown> | InvalidJSONValue,
U extends StatusCode = StatusCode
>(
object: T,

I've just given a quick look but JSONValue seems to be used in two ways:

  • the type of a candidate value to be converted by JSON.stringify
  • the type of a already converted value by JSON.stringify
    • like

      hono/src/types.ts

      Lines 1902 to 1910 in 4d33e1c

      export type TypedResponse<
      T = unknown,
      U extends StatusCode = StatusCode,
      F extends ResponseFormat = T extends string
      ? 'text'
      : T extends JSONValue
      ? 'json'
      : ResponseFormat
      > = {

I'm not sure but I think it's not so harmful for now. We may need refactoring, though

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the explanation!

How about this? undefined is invalid, but having undefined as the value of a record is valid:

diff --git a/src/context.ts b/src/context.ts
index 8d0aa89e..365161fc 100644
--- a/src/context.ts
+++ b/src/context.ts
@@ -180,7 +180,7 @@ type JSONRespondReturn<
       ? JSONValue extends SimplifyDeepArray<T>
         ? never
         : JSONParsed<T>
-      : JSONParsed<T>,
+      : never,
     U,
     'json'
   >
diff --git a/src/utils/types.ts b/src/utils/types.ts
index 3fd17a94..b6cef375 100644
--- a/src/utils/types.ts
+++ b/src/utils/types.ts
@@ -26,7 +26,9 @@ export type IfAnyThenEmptyObject<T> = 0 extends 1 & T ? {} : T

 export type JSONPrimitive = string | boolean | number | null
 export type JSONArray = (JSONPrimitive | JSONObject | JSONArray)[]
-export type JSONObject = { [key: string]: JSONPrimitive | JSONArray | JSONObject | object }
+export type JSONObject = {
+  [key: string]: JSONPrimitive | JSONArray | JSONObject | object | undefined
+}
 export type InvalidJSONValue = undefined | symbol | ((...args: unknown[]) => unknown)

 type InvalidToNull<T> = T extends InvalidJSONValue ? null : T

Copy link
Contributor Author

@m-shaka m-shaka Jul 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the meaning of the type of a candidate value, it's ok.
You can call ctx.json({ a: undefined }) and the type of output is {}, which is completely correct because the fact that JSON.stringify drops keys with undefined is the specification.
Same as ctx.json({ a: Symbol.for("") }) or ctx.json({ a: () => {} }).

However, in the meaning of the latter case (used as a type constraint of TypedResponse), it's not correct. It expects types being proceeded by JSONParsed, that never have keys with undefined, symbol, or function type.
But, my guess is that in most cases TypedResponse is used through JSONRespondReturn or like that, and JSONValue is used here only for deciding the response format, and types like { a: undefined } should be treated as 'json' format.
That's why I said it's not so harmful.

(I'm not confident if I understand what you mean. Sorry if not.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@m-shaka

Understood well. You are right that the definition of JSONObject is good for now. Sorry for wasting your time. Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No way! Thank you for your patience!

Copy link
Member

@yusukebe yusukebe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@yusukebe yusukebe changed the title fix: degradation of generic type handling fix(type): degradation of generic type handling Jul 22, 2024
@yusukebe yusukebe merged commit 8dc9e48 into honojs:main Jul 22, 2024
14 checks passed
adamnolte referenced this pull request in autoblocksai/cli Aug 9, 2024
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [hono](https://hono.dev/) ([source](https://github.com/honojs/hono))
| [`4.5.1` ->
`4.5.4`](https://renovatebot.com/diffs/npm/hono/4.5.1/4.5.4) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/hono/4.5.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/hono/4.5.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/hono/4.5.1/4.5.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/hono/4.5.1/4.5.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>honojs/hono (hono)</summary>

### [`v4.5.4`](https://github.com/honojs/hono/releases/tag/v4.5.4)

[Compare
Source](https://github.com/honojs/hono/compare/v4.5.3...v4.5.4)

##### What's Changed

- fix(jsx): corrects the type of 'draggable' attribute in
intrinsic-elements.ts by
[@&#8203;yasuaki640](https://github.com/yasuaki640) in
[https://github.com/honojs/hono/pull/3224](https://github.com/honojs/hono/pull/3224)
- feat(jsx): allow to merge CSSProperties declaration by
[@&#8203;jonasnobile](https://github.com/jonasnobile) in
[https://github.com/honojs/hono/pull/3228](https://github.com/honojs/hono/pull/3228)
- feat(client): Add WebSocket Provider Integration Tests and Enhance
WebSocket Initialization by
[@&#8203;naporin0624](https://github.com/naporin0624) in
[https://github.com/honojs/hono/pull/3213](https://github.com/honojs/hono/pull/3213)
- fix(types): `param` in `ValidationTargets` supports optional param by
[@&#8203;yusukebe](https://github.com/yusukebe) in
[https://github.com/honojs/hono/pull/3229](https://github.com/honojs/hono/pull/3229)

##### New Contributors

- [@&#8203;jonasnobile](https://github.com/jonasnobile) made their
first contribution in
[https://github.com/honojs/hono/pull/3228](https://github.com/honojs/hono/pull/3228)

**Full Changelog**:
honojs/hono@v4.5.3...v4.5.4

### [`v4.5.3`](https://github.com/honojs/hono/releases/tag/v4.5.3)

[Compare
Source](https://github.com/honojs/hono/compare/v4.5.2...v4.5.3)

#### What's Changed

- fix(validator): Add double quotation marks to multipart checker regex
by [@&#8203;CPlusPatch](https://github.com/CPlusPatch) in
[https://github.com/honojs/hono/pull/3195](https://github.com/honojs/hono/pull/3195)
- fix(validator): support `application/json` with a charset as JSON by
[@&#8203;yusukebe](https://github.com/yusukebe) in
[https://github.com/honojs/hono/pull/3199](https://github.com/honojs/hono/pull/3199)
- fix(jsx): fix handling of SVG elements in JSX. by
[@&#8203;usualoma](https://github.com/usualoma) in
[https://github.com/honojs/hono/pull/3204](https://github.com/honojs/hono/pull/3204)
- fix(jsx/dom): fix performance issue with adding many new node listings
by [@&#8203;usualoma](https://github.com/usualoma) in
[https://github.com/honojs/hono/pull/3205](https://github.com/honojs/hono/pull/3205)
- fix(service-worker): refer to `self.fetch` correctly by
[@&#8203;yusukebe](https://github.com/yusukebe) in
[https://github.com/honojs/hono/pull/3200](https://github.com/honojs/hono/pull/3200)

#### New Contributors

- [@&#8203;CPlusPatch](https://github.com/CPlusPatch) made their first
contribution in
[https://github.com/honojs/hono/pull/3195](https://github.com/honojs/hono/pull/3195)

**Full Changelog**:
honojs/hono@v4.5.2...v4.5.3

### [`v4.5.2`](https://github.com/honojs/hono/releases/tag/v4.5.2)

[Compare
Source](https://github.com/honojs/hono/compare/v4.5.1...v4.5.2)

#### What's Changed

- fix(helper/adapter): don't check `navigator` is `undefined` by
[@&#8203;yusukebe](https://github.com/yusukebe) in
[https://github.com/honojs/hono/pull/3171](https://github.com/honojs/hono/pull/3171)
- fix(types): handle readonly array correctly by
[@&#8203;m-shaka](https://github.com/m-shaka) in
[https://github.com/honojs/hono/pull/3172](https://github.com/honojs/hono/pull/3172)
- Revert "fix(helper/adapter): don't check `navigator` is `undefined` by
[@&#8203;yusukebe](https://github.com/yusukebe) in
[https://github.com/honojs/hono/pull/3173](https://github.com/honojs/hono/pull/3173)
- fix(type): degradation of generic type handling by
[@&#8203;m-shaka](https://github.com/m-shaka) in
[https://github.com/honojs/hono/pull/3138](https://github.com/honojs/hono/pull/3138)
- fix:(csrf) fix typo of csrf middleware by
[@&#8203;yasuaki640](https://github.com/yasuaki640) in
[https://github.com/honojs/hono/pull/3178](https://github.com/honojs/hono/pull/3178)
- feat(secure-headers): remove "X-Powered-By" should be an option by
[@&#8203;EdamAme-x](https://github.com/EdamAme-x) in
[https://github.com/honojs/hono/pull/3177](https://github.com/honojs/hono/pull/3177)

**Full Changelog**:
honojs/hono@v4.5.1...v4.5.2

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" in timezone
America/Chicago, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View the
[repository job log](https://developer.mend.io/github/autoblocksai/cli).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40NDAuNyIsInVwZGF0ZWRJblZlciI6IjM4LjE4LjE3IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
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.

bug: JSONParsed type not correctly working for generic type
2 participants