TypeScript helpers for consuming openapi-typescript types
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
General-purpose TypeScript utility types for advanced type manipulation, conditional type logic, and media type handling.
Find first match of multiple keys from an object type.
/**
* Find first match of multiple keys
*/
type FilterKeys<Obj, Matchers> = Obj[keyof Obj & Matchers];Usage Examples:
import type { FilterKeys } from "openapi-typescript-helpers";
// Extract values by key pattern
type ApiResponse = {
"application/json": { data: User };
"application/xml": string;
"text/plain": string;
};
// Filter by specific key
type JsonContent = FilterKeys<ApiResponse, "application/json">; // { data: User }
// Filter by key pattern (using template literal types)
type ApplicationTypes = FilterKeys<ApiResponse, `application/${string}`>;
// { data: User } | string
// Multiple object example
type StatusResponses = {
200: { success: true };
400: { error: string };
404: { error: string };
};
type ErrorResponses = FilterKeys<StatusResponses, 400 | 404>; // { error: string }Get the type of a value of an input object with a given key, with fallback default.
/**
* @deprecated Use `FilterKeys` instead
* Get the type of a value of an input object with a given key. If the key is
* not found, return a default type. Works with unions of objects too.
*/
type GetValueWithDefault<Obj, KeyPattern, Default> = Obj extends any
? FilterKeys<Obj, KeyPattern> extends never
? Default
: FilterKeys<Obj, KeyPattern>
: never;Return any string/string media type pattern.
/**
* Return any `[string]/[string]` media type (important because openapi-fetch allows any content response, not just JSON-like)
*/
type MediaType = `${string}/${string}`;Usage Examples:
import type { MediaType } from "openapi-typescript-helpers";
// Type-safe media type validation
function isValidMediaType(type: string): type is MediaType {
return /^[^\/]+\/[^\/]+$/.test(type);
}
// Generic content type handling
type ContentTypeMap<T extends MediaType> = {
[K in T]: unknown;
};
type ApiContent = ContentTypeMap<"application/json" | "text/plain">;
// { "application/json": unknown; "text/plain": unknown }Return media types containing "json".
/**
* Return any media type containing "json" (works for "application/json", "application/vnd.api+json", "application/vnd.oai.openapi+json")
*/
type JSONLike<T> = FilterKeys<T, `${string}/json`>;Usage Examples:
import type { JSONLike } from "openapi-typescript-helpers";
// Extract JSON-compatible content types
type ContentTypes = {
"application/json": { data: User };
"application/vnd.api+json": { data: User[] };
"application/xml": string;
"text/plain": string;
"text/json": { message: string };
};
type JsonOnlyContent = JSONLike<ContentTypes>;
// { data: User } | { data: User[] } | { message: string }
// Use in API response handling
function handleJsonResponse<T>(content: JSONLike<T>): void {
// Only JSON-like content types allowed
}Internal helper for required key detection.
/**
* Helper to get the required keys of an object. If no keys are required, will be `undefined` with strictNullChecks enabled, else `never`
*/
type RequiredKeysOfHelper<T> = {
[K in keyof T]: {} extends Pick<T, K> ? never : K;
}[keyof T];Get the required keys of an object, or never if no keys are required.
/**
* Get the required keys of an object, or `never` if no keys are required
*/
type RequiredKeysOf<T> = RequiredKeysOfHelper<T> extends undefined ? never : RequiredKeysOfHelper<T>;Usage Examples:
import type { RequiredKeysOf } from "openapi-typescript-helpers";
// Check required keys in object types
type User = {
id: string;
name: string;
email?: string;
profile?: UserProfile;
};
type UserRequiredKeys = RequiredKeysOf<User>; // "id" | "name"
// Use in validation
type ValidateRequired<T, K extends RequiredKeysOf<T>> = {
[P in K]: T[P];
};
type RequiredUserFields = ValidateRequired<User, RequiredKeysOf<User>>;
// { id: string; name: string }
// Check if object has required fields
type HasRequired<T> = RequiredKeysOf<T> extends never ? false : true;
type UserHasRequired = HasRequired<User>; // true
type EmptyObjectHasRequired = HasRequired<{}>; // falseFilter objects that have required keys.
/**
* Filter objects that have required keys
* @deprecated Use `RequiredKeysOf` instead
*/
type FindRequiredKeys<T, K extends keyof T> = K extends unknown ? (undefined extends T[K] ? never : K) : K;Check if object contains required keys.
/**
* Does this object contain required keys?
* @deprecated Use `RequiredKeysOf` instead
*/
type HasRequiredKeys<T> = FindRequiredKeys<T, keyof T>;Migration Examples:
// Old approach (deprecated)
type OldRequiredCheck<T> = HasRequiredKeys<T> extends never ? false : true;
// New approach (recommended)
type NewRequiredCheck<T> = RequiredKeysOf<T> extends never ? false : true;
// Old required key extraction (deprecated)
type OldRequiredKeys<T> = FindRequiredKeys<T, keyof T>;
// New required key extraction (recommended)
type NewRequiredKeys<T> = RequiredKeysOf<T>;import type {
FilterKeys,
JSONLike,
RequiredKeysOf,
MediaType
} from "openapi-typescript-helpers";
// Complex content type filtering
type ApiResponseContent = {
"application/json": { data: User; meta: Metadata };
"application/vnd.api+json": { data: User[]; included: Resource[] };
"application/xml": string;
"text/html": string;
};
// Extract JSON content and determine required fields
type JsonContent = JSONLike<ApiResponseContent>;
type JsonRequiredKeys = RequiredKeysOf<JsonContent>;
// Create type-safe content handler
type ContentHandler<T extends MediaType> = (
content: FilterKeys<ApiResponseContent, T>
) => void;
// Use with specific media types
const handleJson: ContentHandler<"application/json"> = (content) => {
// content is properly typed as { data: User; meta: Metadata }
console.log(content.data);
};import type { FilterKeys, RequiredKeysOf } from "openapi-typescript-helpers";
// Create error types with required field validation
type ApiError = {
code: string;
message: string;
details?: Record<string, unknown>;
};
type RequiredErrorFields = RequiredKeysOf<ApiError>; // "code" | "message"
// Ensure error objects have required fields
function createError<T extends Record<RequiredErrorFields, any>>(error: T): T {
return error;
}
// Type-safe error with all required fields
const validError = createError({
code: "VALIDATION_ERROR",
message: "Invalid input provided",
details: { field: "email" }
});Install with Tessl CLI
npx tessl i tessl/npm-openapi-typescript-helpers