UNPKG

@jeroenhuinink/tsmapper

Version:

JSON to Typescript object mapper

188 lines (187 loc) 4.75 kB
/** * The source for the mapper is assumed to be JSON response from an API that is indexed with strings. Every value is unknown. */ export interface Source { [key: string]: unknown; } declare type ValueFieldType = string | number | boolean | Date; interface BaseOptions { /** * Target type */ type?: string; /** * The key to the value. */ key?: string; optional?: boolean; default?: unknown; } export interface ValueOptions extends BaseOptions { /** * Target type */ type?: 'string' | 'boolean' | 'number' | 'date' | 'isodate' | undefined; /** * Function to apply to the value before it is returned */ map?: (value: unknown, source: Source) => unknown; /** * Default value for the entry */ default?: ValueFieldType; } interface ObjectOptions<T = {}> { /** * Target type 'object' */ type?: 'object'; /** * The child mapper */ mapper: Mapper<T>; /** * Default value for the entry */ default?: T; } export interface ArrayOptions<T = {}> { /** * Target type 'array' */ type?: 'array'; /** * The type for the array items * */ itemType: ObjectOptions<T> | EnumArrayOptions<T>; /** * Default value for the entry */ default?: T[]; } export interface EnumArrayOptions<T = {}> { /** * Target type 'array' */ type: 'enum'; /** * The type for the array items * */ map: (s: any) => T; /** * Default value for the entry */ default?: T[]; } export interface EnumOptions<T = {}> { type?: 'enum'; /** * Target type 'enum' */ enum: readonly T[]; } export declare type Options = BaseOptions & (ValueOptions | ObjectOptions | ArrayOptions | EnumArrayOptions | EnumOptions); export declare type MapperField = Options & { key: string; name: string; }; declare type ArrayElement<T> = T extends readonly (infer R)[] ? R : never; declare type InferredFieldType<O extends Options> = O extends never ? never : O extends { type: 'string'; optional: true; } ? string | undefined : O extends { type: 'string'; } ? string : O extends { type: 'number'; optional: true; } ? number | undefined : O extends { type: 'number'; } ? number : O extends { type: 'boolean'; optional: true; } ? boolean | undefined : O extends { type: 'boolean'; } ? boolean : O extends { type: 'date'; optional: true; } ? Date | undefined : O extends { type: 'date'; } ? Date : O extends { type: 'isodate'; optional: true; } ? string | undefined : O extends { type: 'isodate'; } ? string : O extends { type: 'array'; itemType: { type: 'enum'; map: (s: unknown) => infer T; }; optional: true; } ? T[] | undefined : O extends { type: 'array'; itemType: { type: 'enum'; map: (s: unknown) => infer T; }; } ? T[] : O extends { enum: infer T; optional: true; } ? ArrayElement<T> | undefined : O extends { enum: infer T; } ? ArrayElement<T> : O extends { mapper: Mapper<infer T>; optional: true; } ? T | undefined : O extends { mapper: Mapper<infer T>; } ? T : O extends { itemType: { type: 'string'; }; } ? string[] : O extends { itemType: { type: 'number'; }; } ? number[] : O extends { itemType: { mapper: Mapper<infer T>; }; optional: true; } ? T[] | undefined : O extends { itemType: { mapper: Mapper<infer T>; }; } ? T[] : O extends { default: infer T; } ? T : unknown; /** * Type for the set of functions that are used to map values from the source to the target. */ export declare type MapFunctions = { string: (val: unknown) => string; number: (val: unknown) => number; boolean: (val: unknown) => boolean; date: (val: unknown) => Date; isodate: (val: unknown) => string; symbol: (val: unknown) => symbol; undefined: (val: unknown) => string; object: (val: unknown) => string; function: (val: unknown) => unknown; }; export interface ImplicitMapper<T = {}> { field<K extends keyof T, O extends Options>(key: K, options: O): ImplicitMapper<Omit<T, K> & { [key in K]: InferredFieldType<O>; }>; field<K extends string, O extends Options>(key: K, options: O): ImplicitMapper<T & { [key in K]: InferredFieldType<O>; }>; map(source: Source): { [key in keyof T]: T[key]; }; } export interface ExplicitMapper<T> { field<K extends keyof T, O extends Options>(key: K, options: O): ExplicitMapper<T>; map(source: Source): T; } export declare type Mapper<T> = ImplicitMapper<T> | ExplicitMapper<T>; export {};