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

feat(http-status): to generate a type error when generating not empty response with 204 #3759

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type {
} from './types'
import type { ResponseHeader } from './utils/headers'
import { HtmlEscapedCallbackPhase, resolveCallback } from './utils/html'
import type { RedirectStatusCode, StatusCode } from './utils/http-status'
import type { NoContentStatusCode, RedirectStatusCode, StatusCode } from './utils/http-status'
import type { BaseMime } from './utils/mime'
import type {
InvalidJSONValue,
Expand Down Expand Up @@ -121,7 +121,7 @@ interface BodyRespond extends NewResponse {}
*
* @interface TextRespond
* @template T - The type of the text content.
* @template U - The type of the status code.
* @template U - The type of the status code without 204.
*
* @param {T} text - The text content to be included in the response.
* @param {U} [status] - An optional status code for the response.
Expand All @@ -130,21 +130,29 @@ interface BodyRespond extends NewResponse {}
* @returns {Response & TypedResponse<T, U, 'text'>} - The response after rendering the text content, typed with the provided text and status code types.
*/
interface TextRespond {
<T extends string, U extends StatusCode = StatusCode>(
<
T extends string,
U extends Exclude<StatusCode, NoContentStatusCode> = Exclude<StatusCode, NoContentStatusCode>
>(
text: T,
status?: U,
headers?: HeaderRecord
): Response & TypedResponse<T, U, 'text'>
<T extends string, U extends StatusCode = StatusCode>(text: T, init?: ResponseInit): Response &
TypedResponse<T, U, 'text'>
<
T extends string,
U extends Exclude<StatusCode, NoContentStatusCode> = Exclude<StatusCode, NoContentStatusCode>
>(
text: T,
init?: ResponseInit
): Response & TypedResponse<T, U, 'text'>
}

/**
* Interface for responding with JSON.
*
* @interface JSONRespond
* @template T - The type of the JSON value or simplified unknown type.
* @template U - The type of the status code.
* @template U - The type of the status code without 204.
*
* @param {T} object - The JSON object to be included in the response.
* @param {U} [status] - An optional status code for the response.
Expand All @@ -155,15 +163,15 @@ interface TextRespond {
interface JSONRespond {
<
T extends JSONValue | SimplifyDeepArray<unknown> | InvalidJSONValue,
U extends StatusCode = StatusCode
U extends Exclude<StatusCode, NoContentStatusCode> = Exclude<StatusCode, NoContentStatusCode>
>(
object: T,
status?: U,
headers?: HeaderRecord
): JSONRespondReturn<T, U>
<
T extends JSONValue | SimplifyDeepArray<unknown> | InvalidJSONValue,
U extends StatusCode = StatusCode
U extends Exclude<StatusCode, NoContentStatusCode> = Exclude<StatusCode, NoContentStatusCode>
>(
object: T,
init?: ResponseInit
Expand All @@ -172,13 +180,13 @@ interface JSONRespond {

/**
* @template T - The type of the JSON value or simplified unknown type.
* @template U - The type of the status code.
* @template U - The type of the status code without 204.
*
* @returns {Response & TypedResponse<SimplifyDeepArray<T> extends JSONValue ? (JSONValue extends SimplifyDeepArray<T> ? never : JSONParsed<T>) : never, U, 'json'>} - The response after rendering the JSON object, typed with the provided object and status code types.
*/
type JSONRespondReturn<
T extends JSONValue | SimplifyDeepArray<unknown> | InvalidJSONValue,
U extends StatusCode
U extends Exclude<StatusCode, NoContentStatusCode>
> = Response &
TypedResponse<
SimplifyDeepArray<T> extends JSONValue
Expand All @@ -194,7 +202,7 @@ type JSONRespondReturn<
* Interface representing a function that responds with HTML content.
*
* @param html - The HTML content to respond with, which can be a string or a Promise that resolves to a string.
* @param status - (Optional) The HTTP status code for the response.
* @param status - (Optional) The HTTP status code without 204 for the response.
* @param headers - (Optional) A record of headers to include in the response.
* @param init - (Optional) The response initialization object.
*
Expand All @@ -203,7 +211,7 @@ type JSONRespondReturn<
interface HTMLRespond {
<T extends string | Promise<string>>(
html: T,
status?: StatusCode,
status?: Exclude<StatusCode, NoContentStatusCode>,
headers?: HeaderRecord
): T extends string ? Response : Promise<Response>
<T extends string | Promise<string>>(html: T, init?: ResponseInit): T extends string
Expand Down Expand Up @@ -736,7 +744,7 @@ export class Context<
*/
text: TextRespond = (
text: string,
arg?: StatusCode | ResponseInit,
arg?: Exclude<StatusCode, NoContentStatusCode> | ResponseInit,
headers?: HeaderRecord
): ReturnType<TextRespond> => {
// If the header is empty, return Response immediately.
Expand Down Expand Up @@ -769,7 +777,7 @@ export class Context<
*/
json: JSONRespond = <
T extends JSONValue | SimplifyDeepArray<unknown> | InvalidJSONValue,
U extends StatusCode = StatusCode
U extends Exclude<StatusCode, NoContentStatusCode> = Exclude<StatusCode, NoContentStatusCode>
>(
object: T,
arg?: U | ResponseInit,
Expand All @@ -786,7 +794,7 @@ export class Context<

html: HTMLRespond = (
html: string | Promise<string>,
arg?: StatusCode | ResponseInit,
arg?: Exclude<StatusCode, NoContentStatusCode> | ResponseInit,
headers?: HeaderRecord
): Response | Promise<Response> => {
this.#preparedHeaders ??= {}
Expand Down
40 changes: 20 additions & 20 deletions src/types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type {
ToSchema,
TypedResponse,
} from './types'
import type { StatusCode } from './utils/http-status'
import type { NoContentStatusCode, StatusCode } from './utils/http-status'
import type { Equal, Expect } from './utils/types'
import { validator } from './validator'

Expand Down Expand Up @@ -96,7 +96,7 @@ describe('HandlerInterface', () => {
message: string
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand Down Expand Up @@ -135,7 +135,7 @@ describe('HandlerInterface', () => {
message: string
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand Down Expand Up @@ -163,7 +163,7 @@ describe('HandlerInterface', () => {
}
output: 'foo'
outputFormat: 'text'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand Down Expand Up @@ -192,7 +192,7 @@ describe('HandlerInterface', () => {
}
output: string
outputFormat: 'text'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand All @@ -217,7 +217,7 @@ describe('HandlerInterface', () => {
}
output: string
outputFormat: 'text'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
} & {
Expand Down Expand Up @@ -271,7 +271,7 @@ describe('OnHandlerInterface', () => {
success: boolean
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand Down Expand Up @@ -376,7 +376,7 @@ describe('Support c.json(undefined)', () => {
input: {}
output: never
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand Down Expand Up @@ -460,7 +460,7 @@ describe('`json()`', () => {
message: string
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand Down Expand Up @@ -714,7 +714,7 @@ describe('MergeSchemaPath', () => {
}
output: {}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
},
Expand All @@ -733,7 +733,7 @@ describe('MergeSchemaPath', () => {
}
output: {}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand Down Expand Up @@ -902,23 +902,23 @@ describe('Different types using json()', () => {
ng: boolean
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
| {
input: {}
output: {
ok: boolean
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
| {
input: {}
output: {
default: boolean
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand Down Expand Up @@ -974,7 +974,7 @@ describe('Different types using json()', () => {
default: boolean
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand Down Expand Up @@ -1012,23 +1012,23 @@ describe('Different types using json()', () => {
ng: boolean
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
| {
input: {}
output: {
ok: boolean
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
| {
input: {}
output: {
default: boolean
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand Down Expand Up @@ -1084,7 +1084,7 @@ describe('Different types using json()', () => {
default: boolean
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand All @@ -1111,7 +1111,7 @@ describe('json() in an async handler', () => {
ok: boolean
}
outputFormat: 'json'
status: StatusCode
status: Exclude<StatusCode, NoContentStatusCode>
}
}
}
Expand Down
15 changes: 13 additions & 2 deletions src/utils/http-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,20 @@
* @module
* HTTP Status utility.
*/

export type InfoStatusCode = 100 | 101 | 102 | 103
export type SuccessStatusCode = 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226
export type NoContentStatusCode = 204
export type SuccessStatusCode =
| 200
| 201
| 202
| 203
| NoContentStatusCode
| 205
| 206
| 207
| 208
| 226
export type DeprecatedStatusCode = 305 | 306
export type RedirectStatusCode = 300 | 301 | 302 | 303 | 304 | DeprecatedStatusCode | 307 | 308
export type ClientErrorStatusCode =
Expand Down
Loading