TypeScript helpers for consuming openapi-typescript types
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Advanced type utilities for extracting and manipulating OpenAPI path and operation objects, including request/response type extraction and content filtering.
Find all paths that have the given HTTP method.
/**
* Given an OpenAPI Paths Object, find all paths that have the given method
*/
type PathsWithMethod<Paths extends {}, PathnameMethod extends HttpMethod> = {
[Pathname in keyof Paths]: Paths[Pathname] extends {
[K in PathnameMethod]: any;
}
? Pathname
: never;
}[keyof Paths];Usage Examples:
import type { PathsWithMethod, HttpMethod } from "openapi-typescript-helpers";
// Define OpenAPI paths
type ApiPaths = {
"/users": {
get: { responses: { 200: { content: { "application/json": User[] } } } };
post: { requestBody: any; responses: { 201: any } };
};
"/posts": {
get: { responses: { 200: any } };
};
"/admin": {
put: { requestBody: any; responses: { 200: any } };
delete: { responses: { 204: any } };
};
};
// Extract paths that support specific methods
type GetPaths = PathsWithMethod<ApiPaths, "get">; // "/users" | "/posts"
type PostPaths = PathsWithMethod<ApiPaths, "post">; // "/users"
type DeletePaths = PathsWithMethod<ApiPaths, "delete">; // "/admin"Internal interface for OpenAPI operation objects.
/**
* DO NOT USE!
* Only used for OperationObject type inference
*/
interface OperationObject {
parameters: any;
requestBody: any;
responses: any;
}Internal helper for path item objects.
/**
* Internal helper used in PathsWithMethod
*/
type PathItemObject = {
[M in HttpMethod]: OperationObject;
} & { parameters?: any };Return responses for an Operation Object.
/**
* Return `responses` for an Operation Object
*/
type ResponseObjectMap<T> = T extends { responses: any } ? T["responses"] : unknown;Return content for a Response Object.
/**
* Return `content` for a Response Object
*/
type ResponseContent<T> = T extends { content: any } ? T["content"] : unknown;Return all 2XX responses from a Response Object Map.
/**
* Return all 2XX responses from a Response Object Map
*/
type SuccessResponse<
T extends Record<string | number, any>,
Media extends MediaType = MediaType,
> = GetResponseContent<T, Media, OkStatus>;Usage Examples:
import type { SuccessResponse, ResponseObjectMap } from "openapi-typescript-helpers";
// Define operation response
type UserOperation = {
responses: {
200: { content: { "application/json": User; "text/plain": string } };
201: { content: { "application/json": User } };
400: { content: { "application/json": { error: string } } };
};
};
// Extract success responses
type UserSuccess = SuccessResponse<ResponseObjectMap<UserOperation>>;
// Result: User | string (from 200) | User (from 201)
// Filter by media type
type UserSuccessJSON = SuccessResponse<ResponseObjectMap<UserOperation>, "application/json">;
// Result: UserReturn all 5XX and 4XX responses from a Response Object Map.
/**
* Return all 5XX and 4XX responses (in that order) from a Response Object Map
*/
type ErrorResponse<
T extends Record<string | number, any>,
Media extends MediaType = MediaType,
> = GetResponseContent<T, Media, ErrorStatus>;Extract JSON-like responses for success and error cases.
/**
* Return first JSON-like 2XX response from a path + HTTP method
*/
type SuccessResponseJSON<PathMethod extends Record<string | number, any>> = SuccessResponse<
ResponseObjectMap<PathMethod>,
`${string}/json`
>;
/**
* Return first JSON-like 5XX or 4XX response from a path + HTTP method
*/
type ErrorResponseJSON<PathMethod extends Record<string | number, any>> = ErrorResponse<
ResponseObjectMap<PathMethod>,
`${string}/json`
>;Usage Examples:
import type { SuccessResponseJSON, ErrorResponseJSON } from "openapi-typescript-helpers";
// Define path method
type GetUser = {
responses: {
200: {
content: {
"application/json": User;
"application/xml": string;
};
};
404: {
content: {
"application/json": { error: string };
"text/plain": string;
};
};
};
};
// Extract JSON responses only
type UserData = SuccessResponseJSON<GetUser>; // User
type UserError = ErrorResponseJSON<GetUser>; // { error: string }Return type of requestBody for an Operation Object.
/**
* Return type of `requestBody` for an Operation Object
*/
type OperationRequestBody<T> = "requestBody" extends keyof T ? T["requestBody"] : never;Resolve to true if request body is optional, else false.
/**
* Resolve to `true` if request body is optional, else `false`
*/
type IsOperationRequestBodyOptional<T> = RequiredKeysOf<PickRequestBody<T>> extends never ? true : false;Return first content from a Request Object Mapping, allowing any media type.
/**
* Return first `content` from a Request Object Mapping, allowing any media type
*/
type OperationRequestBodyContent<T> = FilterKeys<OperationRequestBodyMediaContent<T>, MediaType> extends never
? FilterKeys<NonNullable<OperationRequestBodyMediaContent<T>>, MediaType> | undefined
: FilterKeys<OperationRequestBodyMediaContent<T>, MediaType>;Return JSON-like request body from a path + HTTP method.
/**
* Return JSON-like request body from a path + HTTP method
*/
type RequestBodyJSON<PathMethod> = JSONLike<FilterKeys<OperationRequestBody<PathMethod>, "content">>;Usage Examples:
import type {
OperationRequestBody,
IsOperationRequestBodyOptional,
RequestBodyJSON
} from "openapi-typescript-helpers";
// Define operation with request body
type CreateUser = {
requestBody: {
content: {
"application/json": { name: string; email: string };
"application/xml": string;
};
};
responses: { 201: { content: { "application/json": User } } };
};
// Extract request body
type CreateUserBody = OperationRequestBody<CreateUser>;
// Result: { content: { "application/json": {...}, "application/xml": string } }
// Check if optional
type IsOptional = IsOperationRequestBodyOptional<CreateUser>; // false
// Extract JSON body
type CreateUserJSON = RequestBodyJSON<CreateUser>; // { name: string; email: string }Internal helper to get object type with only the requestBody property.
/**
* Internal helper to get object type with only the `requestBody` property
*/
type PickRequestBody<T> = "requestBody" extends keyof T ? Pick<T, "requestBody"> : never;Internal helper used in OperationRequestBodyContent.
/**
* Internal helper used in OperationRequestBodyContent
*/
type OperationRequestBodyMediaContent<T> = IsOperationRequestBodyOptional<T> extends true
? ResponseContent<NonNullable<OperationRequestBody<T>>> | undefined
: ResponseContent<OperationRequestBody<T>>;Internal helper for extracting response content with media type filtering.
/**
* Internal helper used for response content extraction
*/
type GetResponseContent<
T extends Record<string | number, any>,
Media extends MediaType = MediaType,
ResponseCode extends keyof T = keyof T,
> = ResponseCode extends keyof T
? {
[K in ResponseCode]: T[K]["content"] extends Record<string, any>
? FilterKeys<T[K]["content"], Media> extends never
? T[K]["content"]
: FilterKeys<T[K]["content"], Media>
: K extends keyof T
? T[K]["content"]
: never;
}[ResponseCode]
: never;Install with Tessl CLI
npx tessl i tessl/npm-openapi-typescript-helpers