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
TypeScript
/**
* 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 { }