Repository: hapijs/hapi (language: javascript)

Issue:
HTTP_METHODS_PARTIAL_LOWERCASE is missing `head`
### Runtime

node.js

### Runtime version

18

### Module version

21

### Last module version without issue

_No response_

### Used with

_No response_

### Any other relevant information

_No response_

### What are you trying to achieve or the steps to reproduce?

We have a controller that must only respond to the `head` method

Hapi works with it by creating a `get` route and then checking `request.method` for `method === "head"`

But types from `@hapi/hapi` do not support `head`!

In `lib/types/utils.d.ts`  line 14:

`export type HTTP_METHODS_PARTIAL_LOWERCASE = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'options';`

All we need to do to fix this is add ` | 'head'` to the list!

### What was the result you got?

`if(method === "head") {`

`typescript: This comparison appears to be unintentional because the types 'HTTP_METHODS_PARTIAL_LOWERCASE' and '"head"' have no overlap. [2367]`

### What result did you expect?

Expected it to work!

I can raise a PR if you want?


Discussion / hints:

Fix patch:
diff --git a/lib/types/index.d.ts b/lib/types/index.d.ts
index ecd95a745..aa19b22f4 100644
--- a/lib/types/index.d.ts
+++ b/lib/types/index.d.ts
@@ -18,10 +18,4 @@ export namespace Utils {
     interface Dictionary<T> {
         [key: string]: T;
     }
-
-    type HTTP_METHODS_PARTIAL_LOWERCASE = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'options';
-
-    type HTTP_METHODS_PARTIAL = Uppercase<HTTP_METHODS_PARTIAL_LOWERCASE> | HTTP_METHODS_PARTIAL_LOWERCASE;
-
-    type HTTP_METHODS = 'HEAD' | 'head' | HTTP_METHODS_PARTIAL;
 }
diff --git a/lib/types/request.d.ts b/lib/types/request.d.ts
index f0711afdd..c987216db 100644
--- a/lib/types/request.d.ts
+++ b/lib/types/request.d.ts
@@ -9,7 +9,7 @@ import { PluginsStates, ServerRealm } from './plugin';
 import { ResponseValue, ResponseObject } from "./response";
 import { RouteRules, RouteSettings } from './route';
 import { Server, ServerAuthSchemeObjectApi } from './server';
-import { HTTP_METHODS_PARTIAL, HTTP_METHODS_PARTIAL_LOWERCASE, PeekListener } from './utils';
+import { HTTP_METHODS, PeekListener } from './utils';
 
 /**
  * User extensible types user credentials.
@@ -192,7 +192,7 @@ export interface RequestInfo {
  */
 export interface RequestRoute<Refs extends ReqRef = ReqRefDefaults> {
     /** the route HTTP method. */
-    method: HTTP_METHODS_PARTIAL;
+    method: Exclude<Lowercase<HTTP_METHODS>, 'head'> | '*';
 
     /** the route path. */
     path: string;
@@ -374,7 +374,7 @@ export interface Request<Refs extends ReqRef = ReqRefDefaults> extends Podium {
     /**
      * The request method in lower case (e.g. 'get', 'post').
      */
-    readonly method: HTTP_METHODS_PARTIAL_LOWERCASE;
+    readonly method: Lowercase<HTTP_METHODS>;
 
     /**
      * The parsed content-type header. Only available when payload parsing enabled and no payload error occurred.
@@ -506,7 +506,7 @@ export interface Request<Refs extends ReqRef = ReqRefDefaults> extends Podium {
      * Can only be called from an 'onRequest' extension method.
      * [See docs](https://hapijs.com/api/17.0.1#-requestsetmethodmethod)
      */
-    setMethod(method: HTTP_METHODS_PARTIAL): void;
+    setMethod(method: HTTP_METHODS | Lowercase<HTTP_METHODS>): void;
 
     /**
      * Changes the request URI before the router begins processing the request where:
diff --git a/lib/types/route.d.ts b/lib/types/route.d.ts
index afbd10128..173964163 100644
--- a/lib/types/route.d.ts
+++ b/lib/types/route.d.ts
@@ -4,7 +4,7 @@ import { ObjectSchema, ValidationOptions, SchemaMap, Schema } from 'joi';
 import { PluginSpecificConfiguration} from './plugin';
 import { MergeType, ReqRef, ReqRefDefaults, MergeRefs, AuthMode } from './request';
 import { ContentDecoders, ContentEncoders, RouteRequestExtType, RouteExtObject, Server } from './server';
-import { Lifecycle, Json, HTTP_METHODS_PARTIAL } from './utils';
+import { Lifecycle, Json, HTTP_METHODS } from './utils';
 
 /**
  * Overrides for `InternalRouteOptionType`. Extend this to have
@@ -924,6 +924,8 @@ export interface RulesProcessor<Refs extends ReqRef = ReqRefDefaults> {
     (rules: MergeRefs<Refs>['Rules'] | null, info: RulesInfo): Partial<RouteOptions<Refs>> | null;
 }
 
+type RouteDefMethods = Exclude<HTTP_METHODS | Lowercase<HTTP_METHODS>, 'HEAD' | 'head'>;
+
 /**
  * A route configuration object or an array of configuration objects where each object contains:
  * * path - (required) the absolute path used to match incoming requests (must begin with '/'). Incoming requests are compared to the configured paths based on the server's router configuration. The
@@ -952,7 +954,7 @@ export interface ServerRoute<Refs extends ReqRef = ReqRefDefaults> {
      * (only when an exact match was not found, and any match with a specific method will be given a higher priority over a wildcard match). Can be assigned an array of methods which has the same
      * result as adding the same route with different methods manually.
      */
-    method: HTTP_METHODS_PARTIAL | HTTP_METHODS_PARTIAL[] | string | string[];
+    method: RouteDefMethods | RouteDefMethods[] | '*';
 
     /**
      * (optional) a domain string or an array of domain strings for limiting the route to only requests with a matching host header field. Matching is done against the hostname part of the header
diff --git a/lib/types/utils.d.ts b/lib/types/utils.d.ts
index 30318d529..feb342e0a 100644
--- a/lib/types/utils.d.ts
+++ b/lib/types/utils.d.ts
@@ -11,18 +11,13 @@ import {
     Request} from './request';
 import { ResponseToolkit, Auth } from './response';
 
-export type HTTP_METHODS_PARTIAL_LOWERCASE = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'options';
-
-export type HTTP_METHODS_PARTIAL =
-    'GET'
-    | 'POST'
-    | 'PUT'
-    | 'PATCH'
-    | 'DELETE'
-    | 'OPTIONS'
-    | HTTP_METHODS_PARTIAL_LOWERCASE;
-
-export type HTTP_METHODS = 'HEAD' | 'head' | HTTP_METHODS_PARTIAL;
+/**
+ * All http parser [supported HTTP methods](https://nodejs.org/api/http.html#httpmethods).
+ */
+export type HTTP_METHODS = 'ACL' | 'BIND' | 'CHECKOUT' | 'CONNECT' | 'COPY' | 'DELETE' | 'GET' | 'HEAD' | 'LINK' | 'LOCK' |
+    'M-SEARCH' | 'MERGE' | 'MKACTIVITY' | 'MKCALENDAR' | 'MKCOL' | 'MOVE' | 'NOTIFY' | 'OPTIONS' | 'PATCH' | 'POST' |
+    'PROPFIND' | 'PROPPATCH' | 'PURGE' | 'PUT' | 'REBIND' | 'REPORT' | 'SEARCH' | 'SOURCE' | 'SUBSCRIBE' | 'TRACE' |
+    'UNBIND' | 'UNLINK' | 'UNLOCK' | 'UNSUBSCRIBE';
 
 export type PeekListener = (chunk: string, encoding: string) => void;
 


Test patch: