Skip to content

Commit

Permalink
Rename package to TZod, add README.md, convert to TString, update exp…
Browse files Browse the repository at this point in the history
…orts, add inline documentation
  • Loading branch information
m10rten committed Jan 6, 2024
1 parent 347701e commit fa2979e
Show file tree
Hide file tree
Showing 13 changed files with 6,013 additions and 2,884 deletions.
5 changes: 5 additions & 0 deletions .changeset/empty-ads-bow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@mvdlei/tzod": patch
---

Rename to TZod. Added `README.md`. Converted to `TString`. Updated exports from `t.ts`. Added inline Documentation.
123 changes: 123 additions & 0 deletions packages/zod/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# tzod - TypeScript Utility Library

## Overview

The `tzod` library is a TypeScript utility library that extends the capabilities of the [Zod](https://github.com/colinhacks/zod) validation library. It provides a set of utility functions for common tasks related to strings, numbers, arrays, objects, and more. Below is an overview of the key files and functionalities within the library.

## Files

### `t.ts`

The `T` class serves as the central point of access to the utility functions provided by the library. It includes properties for string operations (`string`), type checking (`is`), type coercion (`to`), array manipulation (`array`), number operations (`number`), and object operations (`object`).

```typescript
const { t } = require("@mvdlei/tzod/t");

console.log(t.is.string("Hello")); // true
console.log(t.to.string(42)); // "42"
console.log(t.string.lower("HELLO")); // "hello"
console.log(t.number.is.even(6)); // true
console.log(t.object.merge({ a: 1 }, { b: 2 })); // { a: 1, b: 2 }
console.log(t.array.shuffle([1, 2, 3])); // [2, 1, 3]
```

### `to.ts`

This file defines the `ITo` interface and its implementation class `To`. It contains functions for coercing values to various types, such as string, number, boolean, etc. The `To` class utilizes Zod for type coercion.

```typescript
const { to } = require("@mvdlei/tzod/t");

console.log(to.string(42)); // "42"
console.log(to.number("42")); // 42
console.log(to.array(123)); // [123]
```

### `string.ts`

The `TString` class and `IString` interface define functions for string manipulations, such as converting to uppercase or lowercase, reversing, checking for emptiness, and more.

```typescript
const { string } = require("@mvdlei/tzod/t");

// fully typesafe
console.log(string.upper("hello")); // "HELLO"
console.log(string.lower("HELLO")); // "hello"
console.log(string.reverse("world")); // "dlrow"
// use t.is.string and t.is.falsy to check for emptiness and type safety as this will not satisfy the compiler
console.log(string.empty("")); // true
```

### `object.ts`

The `TObject` class and `IObject` interface offer functions for working with objects, including merging, extracting keys, freezing, unfreezing, filtering based on a predicate, selecting specific keys, and excluding specific keys.

```typescript
const { object } = require("@mvdlei/tzod/t");

console.log(object.merge({ a: 1, b: 1 }, { b: 2 })); // { a: 1, b: 2 }
console.log(object.keys({ x: 1, y: 2 })); // ["x", "y"]
console.log(object.freeze({ a: 1 })); // { a: 1 }
console.log(object.unfreeze({ a: 1 })); // { a: 1 }
// filter on values
console.log(object.filter({ a: 1, b: 2 }, (key, value) => value === 1)); // { a: 1 }
// fully typesafe
console.log(object.select({ a: 1, b: 2 }, ["a"])); // { a: 1 }
console.log(object.exclude({ a: 1, b: 2 }, ["a"])); // { b: 2 }
```

### `number.ts`

The `TNumber` class and `INumber` interface provide number-related functionalities, such as parsing numbers from strings, constraining values within a range, checking for odd/even, and calculating percentages.

```typescript
const { number } = require("@mvdlei/tzod/t");

// number.is for value checking
console.log(number.is.even(6)); // true
console.log(number.is.between(5, 1, 10)); // true
// utility functions
console.log(number.constrain(5, 1, 10)); // 5
console.log(number.parse("42")); // 42
console.log(number.percent(25, 50)); // 50, add the % sign if needed
```

### `is.ts`

The `Is` class and `IIs` interface define type checking functions for various data types, including strings, numbers, null, undefined, boolean, bigint, symbol, object, array, date, error, promise, and more.

```typescript
const { is } = require("@mvdlei/tzod/t");

console.log(is.string("Hello")); // true
console.log(is.number(42)); // true
console.log(is.object({})); // true
```

### `array.ts`

The `TArray` class and `IArray` interface contain an array utility function to shuffle elements randomly.

```typescript
const { array } = require("@mvdlei/tzod/t");
// based on Math.random()
console.log(array.shuffle([1, 2, 3])); // [2, 1, 3]
```

## Usage

To use the `tzod` library, import the `t` object from the `t.ts` file. For example:

```typescript
import t from "@mvdlei/tzod/t";

const result = t.is.string("Hello"); // true
```

Explore the various utility functions provided by each class for your specific needs. Refer to the inline comments and JSDoc for detailed information on each function.

## Note

Please note that the library makes use of [Zod](https://github.com/colinhacks/zod) for type validation and coercion. Ensure that you have the Zod library installed in your project for the `tzod` library to function correctly.

Feel free to extend or modify the library to suit your requirements. Contributions and improvements are welcome!
4 changes: 2 additions & 2 deletions packages/zod/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@mvdlei/zod",
"name": "@mvdlei/tzod",
"version": "0.1.0",
"description": "Zod Preset and Extension. Includes Schemas, Types, Base interfaces and more.",
"description": "Zod Preset and Extensions. Includes Schemas, Types, Base interfaces and more.",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
Expand Down
5 changes: 5 additions & 0 deletions packages/zod/src/array.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
export interface IArray {
/**
* Shuffle an array
* @param array
* @returns Shuffled array
*/
shuffle: <T>(array: T[]) => T[];
}

Expand Down
24 changes: 24 additions & 0 deletions packages/zod/src/g.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/no-namespace */
/**
* Pretty a type for better readability
*/
export type Pretty<T> = { [K in keyof T]: T[K] } & unknown;

/**
* Falsy values
*/
export type Falsy = undefined | null | false | 0 | "";
/**
* Awaitable type for type casting in TypeScript
* @template T
*/
export type Awaitable<T> = Promise<T> | PromiseLike<T>;

/**
* Guard type for type narrowing in TypeScript
* @template T
*/
export type Guard<T> = (value: unknown) => value is T;
/**
* Coerce type for type casting in TypeScript
* @template T
*/
export type Coerce<T> = (value: unknown) => T;
/**
* Check type for type checking in TypeScript
* @template V
* @template T
*/
export type Check<V, T> = V extends T ? true : false;

export namespace T {
Expand Down
54 changes: 50 additions & 4 deletions packages/zod/src/is.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,74 @@ import type { Awaitable, Falsy, Guard } from "./g";
* Interface for the `is` property of `T`
*/
export interface IIs {
/**
* Check if a value is a string
*/
string: Guard<string>;
/**
* Check if a value is a number
*/
number: Guard<number>;
/**
* Check if a value is null
*/
null: Guard<null>;
/**
* Check if a value is undefined
*/
undefined: Guard<undefined>;
/**
* Check if a value is a boolean
*/
boolean: Guard<boolean>;
/**
* Check if a value is a bigint
*/
bigint: Guard<bigint>;
/**
* Check if a value is a symbol
*/
symbol: Guard<symbol>;
/**
* Check if a value is an object
*/
object: Guard<object>;
function: Guard<(() => unknown) | Function | Awaitable<unknown>>;
/**
* Check if a value is a function
*/
function: Guard<(() => unknown) | Function | (() => Awaitable<unknown>)>;
/**
* Check if a value is any
*/
any: Guard<any>;
/**
* Check if a value is an array
*/
array: Guard<unknown[]>;
/**
* Check if a value is a date
*/
date: Guard<Date>;
/**
* Check if a value is an error
*/
error: Guard<Error>;
/**
* Check if a value is a promise, please note that this is not for async functions that do not return a promise.
*/
promise: Guard<Awaitable<unknown>>;
/**
* Check if a value is falsy
*/
falsy: Guard<Falsy>;
/**
* Check if a value is a zod schema
*
*/
schema: <C extends z.ZodTypeAny>(c: C, v: unknown) => v is C;
/**
* Because of the way `instanceof` works, you are required to pass the class or Object as second argument.
* The first argument is a class or object instance you want to check against.
* @param c
* @param v
* @returns
*/
of: <C>(c: C, v: unknown) => v is C;
}
Expand Down
40 changes: 34 additions & 6 deletions packages/zod/src/number.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,50 @@
export interface INumber {
/**
* Parse a string or number into a number
*/
parse: <N extends string | number>(value: N) => ParseReturn<N>;
/**
* Constrain a number between a min and max value
* @returns Number between min and max or min or max
*/
constrain: (value: number, min: number, max: number) => number;
is: ICheckers;
/**
* NumberChecks for numbers
*/
is: INumberChecks;
/**
* Get a percentage of a number relative to a total
* @returns Percentage of value relative to total (0-100) up to 2 decimal places, ! Does not include % symbol
*/
percent: (value: number, total: number) => number;
}

type ParseReturn<T> = T extends string ? ParseNumber<T> : T extends number ? T : never;
type ParseNumber<T extends string> = T extends `${infer D extends number}` ? D : never;

export interface ICheckers {
export interface INumberChecks {
/**
* Check if a number is odd
*/
odd: (value: number) => boolean;
/**
* Check if a number even
*/
even: (value: number) => boolean;
/**
* Check if a number is between a min and max value
*/
between: (value: number, min: number, max: number) => boolean;
/**
* If the number is safe to use, eg NaN is not safe, Infinity is not safe, etc.
* @param value
* @returns
*/
safe: (value: number) => boolean;
}
class Checkers implements ICheckers {

/**
* NumberChecks class for number related checks
*/
class NumberChecks implements INumberChecks {
odd(value: number): boolean {
return !this.even(value);
}
Expand All @@ -40,8 +65,11 @@ class Checkers implements ICheckers {
}
}

/**
* TNumber class for number related functions and utilities
*/
export class TNumber implements INumber {
public is = new Checkers();
public is = new NumberChecks();
public parse<N extends string | number>(value: N): ParseReturn<N> {
return (typeof value === "string" ? parseInt(value) : value) as ParseReturn<N>;
}
Expand Down
39 changes: 26 additions & 13 deletions packages/zod/src/object.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
import type { Pretty } from "./g";

export interface IObject {
/**
* Merge two objects
*/
merge: <T extends object, U extends object>(a: T, b: U) => Pretty<T & U>;
/**
* Get the keys of an object
*/
keys: <T extends object>(a: T) => (keyof T)[];
/**
* Freeze an object
*/
freeze: <T extends object>(a: T) => Readonly<T>;
/**
* Unfreeze an object
*/
unfreeze: <T extends object>(a: Readonly<T>) => T;
/**
* Filter an object by key and value
*/
filter: <T extends object>(
a: T,
fn: (key: keyof T, value: T[keyof T]) => boolean,
) => T;
/**
* Select keys from an object
*/
select: <T extends object, U extends keyof T>(a: T, b: U[]) => Pretty<Pick<T, U>>;
/**
* Exclude keys from an object
*/
exclude: <T extends object, U extends keyof T>(a: T, b: U[]) => Pretty<Omit<T, U>>;
// flatten: <T extends object>(a: T) => Pretty<Flatten<T>>;
}

// type Flatten<T> = T extends object ? { [K in keyof T]: T[K] } : T;

type Pretty<T> = { [K in keyof T]: T[K] } & unknown;
/**
* TObject class for object related methods
*/
export class TObject implements IObject {
public merge<T extends object, U extends object>(a: T, b: U): Pretty<T & U> {
return { ...a, ...b };
Expand Down Expand Up @@ -46,13 +68,4 @@ export class TObject implements IObject {
Object.entries(a).filter(([key]) => !b.includes(key as U)),
) as Pretty<Omit<T, U>>;
}
// public flatten<T extends object>(a: T): Pretty<Flatten<T>> {
// return Object.fromEntries(
// Object.entries(a).map(([key, value]) => {
// return typeof value === "object"
// ? Object.entries(value).map(([k, v]) => [`${key}.${k}`, v])
// : [key, value];
// }),
// ) as Pretty<Flatten<T>>;
// }
}
Loading

0 comments on commit fa2979e

Please sign in to comment.