UNPKG

@zimic/http

Version:

Next-gen TypeScript-first HTTP utilities

105 lines (97 loc) 3.61 kB
import { ArrayKey, IfNever, NonArrayKey } from '@zimic/utils/types'; /** A schema for strict HTTP form data. */ export interface HttpFormDataSchema { [fieldName: string]: string | string[] | Blob | Blob[] | null | undefined; } export namespace HttpFormDataSchema { /** A schema for loose HTTP form data. Field values are not strictly typed. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export type Loose = Record<string, any>; } export namespace HttpFormDataSchemaName { /** Extracts the names of the form data fields defined in a {@link HttpFormDataSchema} that are arrays. */ export type Array<Schema extends HttpFormDataSchema> = IfNever<Schema, never, ArrayKey<Schema> & string>; /** Extracts the names of the form data fields defined in a {@link HttpFormDataSchema} that are not arrays. */ export type NonArray<Schema extends HttpFormDataSchema> = IfNever<Schema, never, NonArrayKey<Schema> & string>; } /** * Extracts the names of the form data fields defined in a {@link HttpFormDataSchema}. Each key is considered a field * name. `HttpFormDataSchemaName.Array` can be used to extract the names of array form data fields, whereas * `HttpFormDataSchemaName.NonArray` extracts the names of non-array form data fields. * * @example * import { type HttpFormDataSchemaName } from '@zimic/http'; * * type FormDataName = HttpFormDataSchemaName<{ * title: string; * descriptions: string[]; * content: Blob; * }>; * // "title" | "descriptions" | "content" * * type ArrayFormDataName = HttpFormDataSchemaName.Array<{ * title: string; * descriptions: string[]; * content: Blob; * }>; * // "descriptions" * * type NonArrayFormDataName = HttpFormDataSchemaName.NonArray<{ * title: string; * descriptions: string[]; * content: Blob; * }>; * // "title" | "content" */ export type HttpFormDataSchemaName<Schema extends HttpFormDataSchema> = IfNever<Schema, never, keyof Schema & string>; type PrimitiveHttpFormDataSerialized<Type> = [Type] extends [never] ? never : Type extends number ? `${number}` : Type extends boolean ? `${boolean}` : Type extends null ? 'null' : Type extends symbol ? never : Type extends HttpFormDataSchema[string] ? Type : Type extends (infer ArrayItem)[] ? ArrayItem extends (infer _InternalArrayItem)[] ? never : PrimitiveHttpFormDataSerialized<ArrayItem>[] : string; /** * Recursively converts a schema to its {@link https://developer.mozilla.org/docs/Web/API/FormData FormData}-serialized * version. Numbers, booleans, and null are converted to `${number}`, `${boolean}`, and 'null' respectively, and other * values become strings. * * @example * import { type HttpFormDataSerialized } from '@zimic/http'; * * type Schema = HttpFormDataSerialized<{ * contentTitle: string; * contentSize: number | null; * content: Blob; * full?: boolean; * }>; * // { * // contentTitle: string; * // contentSize? `${number}` | 'null'; * // content: Blob; * // full?: "false" | "true"; * // } */ export type HttpFormDataSerialized<Type> = [Type] extends [never] ? never : Type extends HttpFormDataSchema ? Type : Type extends object ? { [Key in keyof Type as IfNever< PrimitiveHttpFormDataSerialized<Type[Key]>, never, Key >]: PrimitiveHttpFormDataSerialized<Type[Key]>; } : never;