From f2b8230ee2dde682b3b20b3dcc76b08f0fd538f7 Mon Sep 17 00:00:00 2001 From: mpppk Date: Mon, 16 Sep 2024 00:41:42 +0900 Subject: [PATCH 1/2] Allow to omit headers and body if they are all optional --- src/common/type.t-test.ts | 10 ++++++++++ src/common/type.ts | 3 +++ src/fetch/index.t-test.ts | 17 +++++++++++++++++ src/fetch/index.ts | 11 +++++++++-- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/common/type.t-test.ts b/src/common/type.t-test.ts index 056945e..2ab419a 100644 --- a/src/common/type.t-test.ts +++ b/src/common/type.t-test.ts @@ -3,6 +3,7 @@ import { CountChar, ExtractByPrefix, FilterNever, + IsAllOptional, IsEqualNumber, Replace, ReplaceAll, @@ -108,3 +109,12 @@ type SameSlashNumTestCases = [ Expect, true>>, Expect, false>>, ]; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +type IsAllOptionalTestCases = [ + Expect, true>>, + Expect, true>>, + Expect, false>>, + Expect, false>>, + Expect, true>>, +]; diff --git a/src/common/type.ts b/src/common/type.ts index b949ffe..d950a11 100644 --- a/src/common/type.ts +++ b/src/common/type.ts @@ -142,3 +142,6 @@ export type SameSlashNum = IsEqualNumber< CountChar, CountChar >; + +// eslint-disable-next-line @typescript-eslint/ban-types +export type IsAllOptional = {} extends T ? true : false; diff --git a/src/fetch/index.t-test.ts b/src/fetch/index.t-test.ts index 890d899..ec028ab 100644 --- a/src/fetch/index.t-test.ts +++ b/src/fetch/index.t-test.ts @@ -143,6 +143,23 @@ const JSONT = JSON as JSONT; })(); } +{ + type Spec = DefineApiEndpoints<{ + "/users": { + post: { + headers: { "Content-Type"?: "application/json" }; + body: { userName?: string }; + responses: { 200: { body: { prop: string } } }; + }; + }; + }>; + (async () => { + const f = fetch as FetchT<"", Spec>; + // headers and body can be omitted because they are optional + await f(`/users`, {}); + })(); +} + { type Spec = DefineApiEndpoints<{ "/packages/list": { diff --git a/src/fetch/index.ts b/src/fetch/index.ts index bcc3294..0f57e75 100644 --- a/src/fetch/index.ts +++ b/src/fetch/index.ts @@ -13,6 +13,7 @@ import { PathToUrlParamPattern, Replace, StatusCode, + IsAllOptional, } from "../common"; import { UrlPrefixPattern, ToUrlParamPattern } from "../common"; import { TypedString } from "../json"; @@ -26,9 +27,15 @@ export type RequestInitT< method?: InputMethod; } & FilterNever<{ // eslint-disable-next-line @typescript-eslint/no-explicit-any - body: Body extends Record ? TypedString : never; + body: Body extends Record + ? IsAllOptional extends true + ? Body | TypedString | undefined + : TypedString + : never; headers: HeadersObj extends Record - ? HeadersObj | Headers + ? IsAllOptional extends true + ? HeadersObj | Headers | undefined + : HeadersObj | Headers : never; }>; From ea5300fea977aab47d3ca44c2065a03b7264afcf Mon Sep 17 00:00:00 2001 From: mpppk Date: Mon, 16 Sep 2024 00:42:35 +0900 Subject: [PATCH 2/2] Fix --- src/common/type.t-test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/type.t-test.ts b/src/common/type.t-test.ts index 2ab419a..a4dd0dd 100644 --- a/src/common/type.t-test.ts +++ b/src/common/type.t-test.ts @@ -112,6 +112,7 @@ type SameSlashNumTestCases = [ // eslint-disable-next-line @typescript-eslint/no-unused-vars type IsAllOptionalTestCases = [ + // eslint-disable-next-line @typescript-eslint/ban-types Expect, true>>, Expect, true>>, Expect, false>>,