Castage is a TypeScript library for type-safe, dynamic data casting, ensuring runtime type validation while leveraging TypeScript's static type guarantees.
Run the following command to install:
npm install castage- Type-safe casting: Validate and transform objects with strict type guarantees.
- Runtime validation: Validate types beyond TypeScript's compile-time checks.
- Flexible APIs: Support for primitive types, schemas, and custom validations.
import { int, string } from 'castage';
const result = int(42);
if (result.isOk) {
console.log(result.value); // 42
}
const result2 = string(42);
if (result2.isErr) {
console.error(result2.error); // CastingError
}import { struct, int, string } from 'castage';
const User = struct({
id: int,
name: string
});
const result = User({ id: 1, name: 'Alice' });
if (result.isOk) {
console.log(result.value); // { id: 1, name: 'Alice' }
}import { array, int } from 'castage';
const intArray = array(int);
const result = intArray([1, 2, 3]);
if (result.isOk) {
console.log(result.value); // [1, 2, 3]
}The main interface for creating and managing data casters.
interface CasterFn<T> {
(value: unknown, path?: string[]): Result<T, CastingError>;
}
interface UnpackCasterFn<T> {
(value: unknown, path?: string[]): T;
}
interface Caster<T> extends CasterFn<T> {
nullable: Caster<T | null>;
optional: Caster<T | undefined>;
default(value: T, name?: string): Caster<T>;
unpack: UnpackCasterFn<T>;
validate<S extends T>(
predicate: (value: T) => value is S,
name?: string,
error?: (value: T, path: string[]) => CastingError,
): Caster<S>;
validate(
predicate: (value: T) => boolean,
name?: string,
error?: (value: T, path: string[]) => CastingError,
): Caster<T>;
match<S, E>(
okMatcher: (data: T) => S,
errMatcher: (err: CastingError) => E,
): UnpackCasterFn<S | E>;
unpackOr<E>(handleError: (err: CastingError) => E): UnpackCasterFn<T | E>;
map<S>(transform: (data: T) => S, name?: string): Caster<S>;
chain<S>(
casterFn: (data: T, path?: string[]) => Result<S, CastingError>,
name?: string,
): Caster<S>;
parse(value: unknown, path?: string[]): Result<T, CastingError[]>;
assert(value: unknown, path?: string[]): asserts value is T;
}Where the Result type is imported from the resultage package.
Describes an error encountered during the casting process.
interface CastingError extends Error {
[$castingError]: true;
code: CastingErrorCode;
path: string[];
extra: Extra;
}int: Ensures the value is an integer.string: Ensures the value is a string.boolean: Ensures the value is a boolean.number: Ensures the value is a number.value: Ensures the value is a specific value.values: Ensures the value is one of the specified values.nill: Ensures the value isnull.undef: Ensures the value isundefined.
any: Ensures the value is any type.unknown: Ensures the value is unknown.
Validates an array of values using a specific caster.
import { array, int } from 'castage';
const intArrayCaster = array(int);
const result = intArrayCaster([1, 2, 3]);
if (result.isOk) {
console.log(result.value); // [1, 2, 3]
}Validates a tuple of values using specific casters.
import { tuple, int, string } from 'castage';
const tupleCaster = tuple(int, string);
const result = tupleCaster([42, 'Alice']);
if (result.isOk) {
console.log(result.value); // [42, 'Alice']
}Validates a structured object with specific type requirements.
import { struct, int, string } from 'castage';
const userCaster = struct({
id: int,
name: string
});
const result = userCaster({ id: 1, name: 'Alice' });
if (result.isOk) {
console.log(result.value); // { id: 1, name: 'Alice' }
}Validates a record with specific key and value types.
import { record, int, string } from 'castage';
const userRecordCaster = record(string, int);
const result = userRecordCaster({ Alice: 1, Bob: 2 });
if (result.isOk) {
console.log(result.value); // { Alice: 1, Bob: 2 }
}Validates a value against multiple possible types.
import { oneOf, int, string } from 'castage';
const mixedTypeCaster = oneOf(int, string);
const result1 = mixedTypeCaster(42);
if (result1.isOk) {
console.log(result1.value); // 42
}
const result2 = mixedTypeCaster('Alice');
if (result2.isOk) {
console.log(result2.value); // 'Alice'
}
const result3 = mixedTypeCaster(true);
if (result3.isErr) {
console.error(result3.error); // CastingError
}Validates a value against multiple possible types.
import { allOf, struct, int, string } from 'castage';
const mixedTypeCaster = allOf(
struct({ id: int }),
struct({ name: string })
);
const result = mixedTypeCaster({ id: 42, name: "Alice" });
if (result.isOk) {
console.log(result.value); // { id: 42, name: "Alice" }
} else {
console.error(result.error); // CastingError
}
---
## Error Handling
Casting errors provide detailed information about failures:
```ts
interface CastingError {
code: CastingErrorCode;
path: string[];
extra: Extra;
}Use isCastingError to check for casting errors:
import { isCastingError } from 'castage';
if (isCastingError(error)) {
console.error(error.path, error.code);
}