ts-data-objects
Version:
Simple lightweight library for enhancing plain JS objects with TypeScript wrappers enabling easy API data assertion and validation
293 lines (279 loc) • 10.1 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>;
/**
* 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;
/**
* 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>;
};
export { }