UNPKG

ts-data-objects

Version:

Simple lightweight library for enhancing plain JS objects with TypeScript wrappers enabling easy API data assertion and validation

509 lines (482 loc) 17.2 kB
/** * Type signature for data object constructor functions. * Creates a function that accepts partial data and returns complete typed objects. * @template T - The object type to be constructed * @param [o] - Optional partial input data * @returns A complete object of type T * @category Core Implementation */ declare type DataConstructor<T extends object> = (o?: Expect<T>) => T; /** * Creates a TypeScript type guard function for runtime type validation. * * Generates a type-safe validation function that: * - Performs runtime type checking * - Provides TypeScript type assertions * - Supports partial input validation based on predicate * * * @example * ```typescript * import { dataGuard } from 'ts-data-objects/core' * import { isStr, isNum } from 'ts-data-objects/common' * * type UserData = { * name: string * age: number * verified?: boolean * } * * // Here we define a function predicate, where `o` is the JSON object * // and we expect it to contain the attributes of the types we expect * const isUserData = dataGuard<UserData>(o => ( * isStr(o?.name) && * isNum(o?.age) * )) * * // Usage: * if (isUserData(someData)) { * //TypeScript now knows `someData` is `UserData` * console.log(someData.name) * } * ``` * * @template T - The object type to create a guard for * @param predicate - Validation function that checks type constraints * @returns A type guard function that asserts input is of type T * @category Core Component */ export declare const dataGuard: <T extends object>(predicate: GuardPredicate<T>) => DataObjectGuard<T>; /** * Creates a typed constructor function for data objects with optional default values. * * This function generates a constructor that: * - Enforces TypeScript type safety * - Merges default values with provided data * - Handles partial input data * * * @example * ```typescript * import { dataObject } from 'ts-data-objects/core' * * type UserData = { * name: string * age: number * verified?: boolean * } * * // Here you can optionally define any default values * // that you might want to be included when parsing JSON data * // or just creating JS Object from scratch * const User = dataObject<UserData>({ * name: '', * verified: false * }) * * // Usage: * const user = User({ name: "John", age: 20 }) * // Result: { name: "John", , age: 20, verified: false } * ``` * * Notes: * - Name collision with TS interface is possible and will work * - The constructor performs shallow merge of objects! This means * that nested objects are replaced rather than copied * * --- * * @template T - The object type/interface to create a constructor for * @param [defaultValues] - Optional default values for the object properties * @returns A constructor function that creates objects of type T * @category Core Component */ export declare const dataObject: <T extends object>(defaultValues?: Expect<T>) => DataConstructor<T>; /** * Type signature for type guard functions that provide TypeScript type assertions. * * Note: * - As pure predicate wouldn't be able to have assertion return type `returnValue is SomeType`, the predicates are wrapped in guard assertions * * @template T - The object type to guard * @param [o] - Optional partial input data to check * @returns Type predicate asserting the input is of type T * @category Core Component */ declare type DataObjectGuard<T extends object> = (o?: Expect<T>) => o is T; /** * Creates a type-safe parser that validates and constructs data objects. * * Combines validation and construction into a single function that: * - Validates input data against type constraints * - Constructs a proper typed object if valid * - Handles validation failures * * @example * ```typescript * import { dataParser } from 'ts-data-objects/core' * * type UserData = { * name: string * age: number * verified?: boolean * } * * // ... with defined constructor and data guard ... * * const parseUser = dataParser<UserData>( * 'UserData', * UserData, // constructor from dataObject * isUserData, // guard from dataGuard * ) * * // Usage: * const user = parseUser(someData) // throws if invalid * // If the code continues, it was successfully parsed * console.log(user.name) * ``` * * @template T - The type to parse into * @param dataType - Type name for error messages * @param constructorFunction - Object constructor function (returned by `dataObject()`) * @param guardFunction - Type guard function (returned by `dataGuard()`) * @param [doNotThrow=false] - If true, logs errors instead of throwing * @returns A function that parses unknown data into type T * @category Core Component */ export declare const dataParser: <T extends object>(dataType: string, constructorFunction: DataConstructor<T>, guardFunction: DataObjectGuard<T>, doNotThrow?: boolean) => DataConstructor<T>; /** * Custom internal error class for data validation failures. * * Provides detailed error messages when data validation fails, including: * - The expected data type name * - The actual value that failed validation * - Optional details about which specific validation failed * * @example * ```typescript * throw new DataValidationError('UserData', invalidData, 'age must be a number') * ``` * * @category Core Component */ export declare class DataValidationError extends Error { /** Name of the expected type */ dataType: string; /** The value that failed validation */ value: unknown; /** Optional details about the validation failure */ detail?: string; constructor( /** Name of the expected type */ dataType: string, /** The value that failed validation */ value: unknown, /** Optional details about the validation failure */ detail?: string); } /** * Complete object definition combining constructor, guard, and parser functions. * Provides a unified interface for working with typed data objects. * - Combined parts with {@link NamedConstructor}, {@link NamedGuard} and {@link NamedParser} * * @template Type - The object type being defined * @template TypeName - The name to use for generated functions * @category Core Implementation */ declare type DefinedObject<Type extends object, TypeName extends string> = NamedConstructor<Type, TypeName> & NamedGuard<Type, TypeName> & NamedParser<Type, TypeName>; /** * Creates a complete suite of functions for working with typed data objects. * Combines object construction, validation, and parsing into a single definition. * * This function generates: * - A constructor function for creating objects with defaults * - A type guard function for validation * - A parser function for safely handling unknown data * * All functions are named based on the provided type name: * - Constructor: [typeName] * - Guard / Validation: is[typeName] * - Parser: parse[typeName] * * @example * ```typescript * import { defineObject } from 'ts-data-objects/core' * import { isStr, isNum } from 'ts-data-objects/common' * * type UserData = { * name: string * age: number * verified?: boolean * } * * const { * UserData, // Constructor * isUserData, // Type guard * parseUserData // Parser * } = defineObject<UserData>('UserData', { * defaultValues: { verified: false }, * predicate: o => ( * isStr(o?.name) && * isNum(o?.age) * ) * }) * * // Usage: * const user = UserData({ name: 'John', age: 20 }) * * if (isUserData(someData)) { * // TypeScript now knows `someData` is now `UserData` * console.log(someData) * } * * // if the apiData is correct according to UserData guard, the data is validated * try { * const receivedUser = parseUserData(apiData) * } * catch (e: any) { * // Handle the error... * } * ``` * * @template Type - The object type to define * @template TypeName - The name to use for generated functions * @param typeName - Name used to generate function names * @param options - Configuration for the object definition, see {@link DefineObjectParams} * @returns Object containing named constructor, guard, and parser functions * @category Core Implementation */ export declare const defineObject: <Type extends object, TypeName extends string>(typeName: TypeName, options: DefineObjectParams<Type>) => DefinedObject<Type, TypeName>; /** * Configuration parameters for creating a complete data object definition. * * @template T - The type of object being defined * @property [defaultValues] - Optional default values for object properties * @property predicate - Validation function for type checking * @property [doNotThrow] - Whether to suppress validation errors * @category Core Implementation */ declare type DefineObjectParams<T extends object> = { defaultValues?: T; predicate: GuardPredicate<T>; doNotThrow?: boolean; }; /** * A semantic alias for TypeScript's `Partial<T>` utility type. * Makes code more readable by explicitly indicating expected partial input. * * @template T - The type to make partial * @category Common Utils */ declare type Expect<T> = Partial<T>; /** * Type signature for predicate functions that validate JSON objects. * Used to check if a partial object matches expected type constraints. * * @template T - The object type to validate * @param [o] - Optional partial input data to validate * @returns Boolean indicating whether the input satisfies type constraints * @category Core Component */ declare type GuardPredicate<T extends object> = (o?: Expect<T>) => boolean; /** * Checks if a value is an array where every element satisfies the provided predicate * * @example * ```typescript * import { isArrayOf, isStr } from 'ts-data-objects' * * if (isArrayOf(someValue, isStr)) { * someValue.push('someValue is string array') * } * ``` * * @template T The expected type of array elements * @param value - The value to check * @param predicate - The type guard function to apply to each array element * @returns A type predicate indicating whether the value is an array of type T * @category Assertions */ export declare const isArrayOf: <T>(value: unknown, predicate: Predicate<T>) => value is T[]; /** * Type guard function for boolean values. * * @example * ```typescript * isBool(true) // returns true * isBool('true') // returns false * isBool(0) // returns false * isBool(null) // returns false * isBool(undefined) // returns false * ``` * * @param value - Any value to check * @returns Type predicate indicating if the value is a boolean * @category Assertions */ export declare const isBool: (value: unknown) => value is boolean; /** * Type guard function for number values. * * @example * ```typescript * isNum(42) // returns true * isNum('42') // returns false * isNum(NaN) // returns true - but will not occur in JSON data * isNum(null) // returns false * isNum(undefined) // returns false * ``` * * @param value - Any value to check * @returns Type predicate indicating if the value is a number * @category Assertions */ export declare const isNum: (value: unknown) => value is number; /** * Checks if a value satisfies the provided simple object predicate * - Intended for user generated TS data objects residing inside other interfaces * * @template T The expected type of the object * @param value - The value to check * @param predicate - The type guard function to check if the value is of type T * @returns A type predicate indicating whether the value is null, undefined, or of type T * @category Assertions */ export declare const isObject: <T>(value: unknown, predicate: Predicate<T> | PredicateFunction) => value is T; /** * Checks if a value is either null, undefined, or an array where every element satisfies the provided predicate * * @template T The expected type of array elements * @param value - The value to check * @param predicate - The type guard function to apply to each array element * @returns A type predicate indicating whether the value is null, undefined, or an array of type T * @category Assertions */ export declare const isOptionalArrayOf: <T>(value: unknown, predicate: Predicate<T>) => value is T[]; /** * Type guard function for optional boolean values * * @example * ```typescript * isBool(true) // returns true * isBool('true') // returns false * isBool(0) // returns false * isBool(null) // returns true * isBool(undefined) // returns true * ``` * * @param value - Any value to check * @returns Type predicate indicating if the value is boolean or null/undefined * @category Assertions */ export declare const isOptionalBool: (value: unknown) => value is boolean; /** * Type guard function for optional number values. * * @example * ```typescript * isNum(42) // returns true * isNum('42') // returns false * isNum(NaN) // returns true * isNum(null) // returns true * isNum(undefined) // returns true * ``` * * @param value - Any value to check * @returns Type predicate indicating if the value is a number * @category Assertions */ export declare const isOptionalNum: (value: unknown) => value is number; /** * Checks if a value is either null, undefined, or satisfies the provided simple object predicate * - Intended for user generated TS data objects residing inside other interfaces * * @template T The expected type of the object * @param value - The value to check * @param predicate - The type guard function to check if the value is of type T * @returns A type predicate indicating whether the value is null, undefined, or of type T * @category Assertions */ export declare const isOptionalObject: <T>(value: unknown, predicate: Predicate<T>) => value is T; /** * Type guard function for string values. * * @example * ```typescript * isStr('hello') // returns true * isStr(42) // returns false * isStr('') // returns true * isStr(null) // returns true * isStr(undefined) // returns true * ``` * * @param value - Any value to check * @returns Type predicate indicating if the value is a string * @category Assertions */ export declare const isOptionalStr: (value: unknown) => value is string; /** * Type guard function for string values. * * @example * ```typescript * isStr('hello') // returns true * isStr(42) // returns false * isStr('') // returns true * isStr(null) // returns false * isStr(undefined) // returns false * ``` * * @param value - Any value to check * @returns Type predicate indicating if the value is a string * @category Assertions */ export declare const isStr: (value: unknown) => value is string; /** * Creates a named constructor function type using the provided type name. * - Example: For name "User", creates { User: (data?) => UserType } * - Part of {@link DefinedObject}. * @category Core Implementation */ declare type NamedConstructor<Type extends object, TypeName extends string> = { [N in TypeName as `${N}`]: DataConstructor<Type>; }; /** * Creates a named type guard function type with 'is' prefix. * - Example: For name "User", creates { isUser: (data?) => data is UserType } * - Part of {@link DefinedObject}. * @category Core Implementation */ declare type NamedGuard<Type extends object, TypeName extends string> = { [N in TypeName as `is${N}`]: DataObjectGuard<Type>; }; /** * Creates a named parser function type with 'parse' prefix. * - Example: For name "User", creates { parseUser: (data?) => UserType } * - Part of {@link DefinedObject}. * @category Core Implementation */ declare type NamedParser<Type extends object, TypeName extends string> = { [N in TypeName as `parse${N}`]: DataConstructor<Type>; }; /** * Type for a predicate function that performs a type guard check * * @template T The type being checked against * @param value - The unknown value to check * @returns A type predicate indicating whether the value is of type T * @category Assertions */ declare type Predicate<T> = (value: unknown) => value is T; /** * A generic predicate function type that tests any value and returns a boolean. * - TS-wise inferior to {@link Predicate}, but is useful when writing custom predicate logic * inside one of functions * * @template T - The type of value being tested (inferred from usage) * @param value - The value to test * @returns A boolean indicating whether the value satisfies the predicate condition * @category Assertions */ declare type PredicateFunction = (value: any) => boolean; export { }