From 5a556e5c5a302353d2964948f329ea05d66de1b7 Mon Sep 17 00:00:00 2001 From: Yamiteru Date: Mon, 29 Apr 2024 21:27:29 +0200 Subject: [PATCH] feat: screw that let's make it simple again --- src/assertions/and/index.test.ts | 5 +-- src/assertions/and/index.ts | 16 ++++++--- src/assertions/and/types.d.ts | 47 --------------------------- src/assertions/and/types.ts | 9 +++++ src/assertions/and2/index.ts | 24 ++++++++------ src/assertions/and3/index.ts | 40 ++++++++++++++--------- src/assertions/array/index.ts | 16 ++++----- src/assertions/array/types.d.ts | 13 -------- src/assertions/boolean/index.ts | 3 +- src/assertions/boolean/types.d.ts | 14 -------- src/assertions/email/index.ts | 3 +- src/assertions/email/types.d.ts | 7 ---- src/assertions/endsWith/index.ts | 14 ++++---- src/assertions/endsWith/types.d.ts | 10 ------ src/assertions/expect/index.ts | 19 +++++------ src/assertions/expect/types.d.ts | 1 - src/assertions/includes/index.ts | 10 +++--- src/assertions/includes/types.d.ts | 7 ---- src/assertions/integer/index.ts | 6 ++-- src/assertions/integer/types.d.ts | 7 ---- src/assertions/isArray/index.ts | 6 ++-- src/assertions/isArray/types.d.ts | 14 -------- src/assertions/isObject/index.ts | 12 ++----- src/assertions/isObject/types.d.ts | 16 --------- src/assertions/lazy/index.ts | 8 ++--- src/assertions/length/index.ts | 10 +++--- src/assertions/length/types.d.ts | 7 ---- src/assertions/maxLength/index.ts | 10 +++--- src/assertions/maxLength/types.d.ts | 7 ---- src/assertions/maxValue/index.ts | 6 ++-- src/assertions/maxValue/types.d.ts | 7 ---- src/assertions/minLength/index.ts | 10 +++--- src/assertions/minLength/types.d.ts | 7 ---- src/assertions/minValue/index.ts | 9 ++--- src/assertions/minValue/types.d.ts | 7 ---- src/assertions/modulo/index.ts | 13 +++----- src/assertions/modulo/types.d.ts | 16 --------- src/assertions/notLength/index.ts | 10 +++--- src/assertions/notLength/types.d.ts | 7 ---- src/assertions/notValue/index.ts | 9 ++--- src/assertions/notValue/types.d.ts | 7 ---- src/assertions/nullable/index.ts | 19 +++++++---- src/assertions/nullable/types.d.ts | 14 -------- src/assertions/nullish/index.ts | 19 +++++++---- src/assertions/nullish/types.d.ts | 10 ------ src/assertions/number/index.ts | 3 +- src/assertions/number/types.d.ts | 14 -------- src/assertions/object/index.ts | 20 ++++++++---- src/assertions/object/types.d.ts | 28 ---------------- src/assertions/optional/index.ts | 20 ++++++++---- src/assertions/optional/types.d.ts | 14 -------- src/assertions/or/index.ts | 27 ++++++++++----- src/assertions/or/types.d.ts | 25 -------------- src/assertions/or2/index.ts | 24 ++++++++------ src/assertions/or3/index.ts | 46 +++++++++++++++----------- src/assertions/rangeLength/index.ts | 14 ++++---- src/assertions/rangeLength/types.d.ts | 13 -------- src/assertions/rangeValue/index.ts | 10 +++--- src/assertions/rangeValue/types.d.ts | 10 ------ src/assertions/regex/index.ts | 9 ++--- src/assertions/regex/types.d.ts | 7 ---- src/assertions/startsWith/index.ts | 14 ++++---- src/assertions/startsWith/types.d.ts | 10 ------ src/assertions/string/index.ts | 3 +- src/assertions/string/types.d.ts | 14 -------- src/assertions/tuple/index.ts | 19 ++++++++--- src/assertions/tuple/types.d.ts | 19 ----------- src/assertions/type/index.ts | 9 ++--- src/assertions/type/types.d.ts | 14 -------- src/assertions/union/index.ts | 11 ++++--- src/assertions/union/types.d.ts | 15 --------- src/assertions/value/index.test-d.ts | 3 +- src/assertions/value/index.ts | 9 ++--- src/assertions/value/types.d.ts | 14 -------- src/types.ts | 24 +------------- src/utils.ts | 29 +++++++++-------- 76 files changed, 325 insertions(+), 697 deletions(-) delete mode 100644 src/assertions/and/types.d.ts create mode 100644 src/assertions/and/types.ts delete mode 100644 src/assertions/array/types.d.ts delete mode 100644 src/assertions/boolean/types.d.ts delete mode 100644 src/assertions/email/types.d.ts delete mode 100644 src/assertions/endsWith/types.d.ts delete mode 100644 src/assertions/expect/types.d.ts delete mode 100644 src/assertions/includes/types.d.ts delete mode 100644 src/assertions/integer/types.d.ts delete mode 100644 src/assertions/isArray/types.d.ts delete mode 100644 src/assertions/isObject/types.d.ts delete mode 100644 src/assertions/length/types.d.ts delete mode 100644 src/assertions/maxLength/types.d.ts delete mode 100644 src/assertions/maxValue/types.d.ts delete mode 100644 src/assertions/minLength/types.d.ts delete mode 100644 src/assertions/minValue/types.d.ts delete mode 100644 src/assertions/modulo/types.d.ts delete mode 100644 src/assertions/notLength/types.d.ts delete mode 100644 src/assertions/notValue/types.d.ts delete mode 100644 src/assertions/nullable/types.d.ts delete mode 100644 src/assertions/nullish/types.d.ts delete mode 100644 src/assertions/number/types.d.ts delete mode 100644 src/assertions/object/types.d.ts delete mode 100644 src/assertions/optional/types.d.ts delete mode 100644 src/assertions/or/types.d.ts delete mode 100644 src/assertions/rangeLength/types.d.ts delete mode 100644 src/assertions/rangeValue/types.d.ts delete mode 100644 src/assertions/regex/types.d.ts delete mode 100644 src/assertions/startsWith/types.d.ts delete mode 100644 src/assertions/string/types.d.ts delete mode 100644 src/assertions/tuple/types.d.ts delete mode 100644 src/assertions/type/types.d.ts delete mode 100644 src/assertions/union/types.d.ts delete mode 100644 src/assertions/value/types.d.ts diff --git a/src/assertions/and/index.test.ts b/src/assertions/and/index.test.ts index c5b5b2a..79586f6 100644 --- a/src/assertions/and/index.test.ts +++ b/src/assertions/and/index.test.ts @@ -2,6 +2,7 @@ import { maxValue } from "@assertions/maxValue"; import { minValue } from "@assertions/minValue"; import { number } from "@assertions/number"; import { fc, test } from "@fast-check/vitest"; +import { assert } from "@utils"; import { expect } from "vitest"; import { and } from "./index"; @@ -10,12 +11,12 @@ const assertion = and([number, minValue(0), maxValue(2)]); test.prop([fc.integer({ min: 0, max: 2 })])( "should not throw if value passes all assertions", (value) => { - expect(() => assertion(value)).not.toThrow(); + expect(() => assert(assertion, value)).not.toThrow(); }, ); test.prop([ fc.oneof(fc.integer({ max: -1 }), fc.integer({ min: 3 }), fc.string()), ])("should throw if value does not pass all assertions", (value) => { - expect(() => assertion(value)).toThrow(); + expect(() => assert(assertion, value)).toThrow(); }); diff --git a/src/assertions/and/index.ts b/src/assertions/and/index.ts index 40461da..6652459 100644 --- a/src/assertions/and/index.ts +++ b/src/assertions/and/index.ts @@ -1,4 +1,5 @@ -import type { AndSchema, Validate } from "@assertions/and/types"; +import type { Assertion } from "@the-minimal/types"; +import type { Intersection } from "./types"; /** * Checks if all the assertions pass. @@ -18,9 +19,14 @@ import type { AndSchema, Validate } from "@assertions/and/types"; * userEmail("yamiteru@icloud.com"); // passes * ``` */ -export const and = (assertions: $Schema) => - ((v: unknown) => { +export const and = + ( + assertions: { + [$Key in keyof $Values]: Assertion<$Values[$Key]>; + }, + ): Assertion> => + (v: unknown) => { for (let i = 0; i < assertions.length; ++i) { - ((assertions as any)[i] as any)(v); + (assertions[i] as any)(v); } - }) as unknown as Validate.And<$Schema>; + }; diff --git a/src/assertions/and/types.d.ts b/src/assertions/and/types.d.ts deleted file mode 100644 index 9295595..0000000 --- a/src/assertions/and/types.d.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { and } from "@assertions/and/index"; -import type { AnyBrand, Brand, None } from "@the-minimal/types"; - -export namespace Validate { - export type And<$Types extends AndSchema> = Brand< - "and", - $Schema, - { - input: InferAndInputs>; - output: InferAndOutputs<$Types>; - } - >; -} - -export type AndSchema = AnyBrand[]; - -export type InferAndInputs<$Types extends unknown[]> = $Types extends [ - infer $Head, - ...infer $Tail, -] - ? $Tail extends [infer _1, ...infer _2] - ? $Head & InferAndOutputs<$Tail> - : $Head - : never; - -type FilterAndInputs<$Schema extends AndSchema> = $Schema extends readonly [ - infer $Head, - ...infer $Tail, -] - ? $Tail extends readonly [infer _1, ...infer _2] - ? $Head extends Brand - ? [$Input, ...FilterAndInputs<$Tail>] - : [] - : $Head extends Brand - ? [$Input] - : [] - : []; - -export type InferAndOutputs<$Schema extends AndSchema> = - $Schema extends readonly [infer $Head, ...infer $Tail] - ? $Tail extends readonly [infer _1, ...infer _2] - ? ($Head extends Brand - ? $Input - : $Head) & - InferAndOutputs<$Tail> - : $Head - : never; diff --git a/src/assertions/and/types.ts b/src/assertions/and/types.ts new file mode 100644 index 0000000..db894a2 --- /dev/null +++ b/src/assertions/and/types.ts @@ -0,0 +1,9 @@ +// TODO: move into @the-minimal/types +export type Intersection<$Values extends unknown[]> = $Values extends [ + infer $Head, + ...infer $Tail, +] + ? $Tail extends [infer _1, ...infer _2] + ? $Head & Intersection<$Tail> + : $Head + : never; diff --git a/src/assertions/and2/index.ts b/src/assertions/and2/index.ts index d10dfec..6dfb395 100644 --- a/src/assertions/and2/index.ts +++ b/src/assertions/and2/index.ts @@ -1,5 +1,8 @@ -import type { Validate } from "@assertions/and/types"; -import type { AnyBrand } from "@the-minimal/types"; +import type { + Assertion, + InferAssertion, + UnknownAssertion, +} from "@the-minimal/types"; /** * Checks that both assertions pass. @@ -16,11 +19,12 @@ import type { AnyBrand } from "@the-minimal/types"; * userEmail("yamiteru@icloud.com"); // passes * ``` */ -export const and2 = <$Brand1 extends AnyBrand, $Brand2 extends AnyBrand>( - brand1: $Brand1, - brand2: $Brand2, -) => - ((v: unknown) => { - (brand1 as any)(v); - (brand2 as any)(v); - }) as unknown as Validate.And<[$Brand1, $Brand2]>; +export const and2 = + <$Assertion1 extends UnknownAssertion, $Assertion2 extends UnknownAssertion>( + assertion1: $Assertion1, + assertion2: $Assertion2, + ): Assertion & InferAssertion<$Assertion2>> => + (v: unknown) => { + assertion1(v); + assertion2(v); + }; diff --git a/src/assertions/and3/index.ts b/src/assertions/and3/index.ts index b9fc7a7..d8ce536 100644 --- a/src/assertions/and3/index.ts +++ b/src/assertions/and3/index.ts @@ -1,5 +1,8 @@ -import type { Validate } from "@assertions/and/types"; -import type { AnyBrand } from "@the-minimal/types"; +import type { + Assertion, + InferAssertion, + UnknownAssertion, +} from "@the-minimal/types"; /** * Checks that all three assertions pass. @@ -18,17 +21,22 @@ import type { AnyBrand } from "@the-minimal/types"; * userEmail("yamiteru@icloud.com"); // passes * ``` */ -export const and3 = < - $Brand1 extends AnyBrand, - $Brand2 extends AnyBrand, - $Brand3 extends AnyBrand, ->( - brand1: $Brand1, - brand2: $Brand2, - brand3: $Brand3, -) => - ((v: unknown) => { - (brand1 as any)(v); - (brand2 as any)(v); - (brand3 as any)(v); - }) as unknown as Validate.And<[$Brand1, $Brand2, $Brand3]>; +export const and3 = + < + $Assertion1 extends UnknownAssertion, + $Assertion2 extends UnknownAssertion, + $Assertion3 extends UnknownAssertion, + >( + assertion1: $Assertion1, + assertion2: $Assertion2, + assertion3: $Assertion3, + ): Assertion< + InferAssertion<$Assertion1> & + InferAssertion<$Assertion2> & + InferAssertion<$Assertion3> + > => + (v: unknown) => { + assertion1(v); + assertion2(v); + assertion3(v); + }; diff --git a/src/assertions/array/index.ts b/src/assertions/array/index.ts index e7a0e82..c6d8922 100644 --- a/src/assertions/array/index.ts +++ b/src/assertions/array/index.ts @@ -1,11 +1,10 @@ import { isArray } from "@assertions/isArray"; -import type { AnyBrand } from "@the-minimal/types"; -import type { Validate } from "./types"; +import type { UnknownAssertion } from "@the-minimal/types"; /** * Checks that assertion passes for each element of the array. * - * @param brand - Assertion to be applied to each element of the array. + * @param assertion - Assertion to be applied to each element of the array. * * @example * ```ts @@ -15,11 +14,12 @@ import type { Validate } from "./types"; * numbers([1, 2, 3]); // passes * ``` */ -export const array = <$Brand extends AnyBrand>(brand: $Brand) => - ((v: any) => { - (isArray as any)(v); +export const array = + <$Assertion extends UnknownAssertion>(assertion: $Assertion) => + (v: unknown) => { + isArray(v); for (let i = 0; i < v.length; ++i) { - (brand as any)((v as any)[i]); + assertion((v as any)[i]); } - }) as unknown as Validate.Array<$Brand>; + }; diff --git a/src/assertions/array/types.d.ts b/src/assertions/array/types.d.ts deleted file mode 100644 index da05318..0000000 --- a/src/assertions/array/types.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { AnyBrand, Brand, None } from "@the-minimal/types"; -import type { InferInput } from "@types"; - -export namespace Validate { - export type Array<$Brand extends AnyBrand> = Brand< - "array", - $Brand, - { - input: InferInput<$Brand>[]; - output: None; - } - >; -} diff --git a/src/assertions/boolean/index.ts b/src/assertions/boolean/index.ts index ed9059f..e13c25f 100644 --- a/src/assertions/boolean/index.ts +++ b/src/assertions/boolean/index.ts @@ -1,5 +1,4 @@ import { type } from "@assertions/type"; -import type { Validate } from "./types"; /** * Checks that the value is a boolean. @@ -10,4 +9,4 @@ import type { Validate } from "./types"; * boolean(true); // passes * ``` */ -export const boolean = type("boolean") as Validate.Type.Boolean; +export const boolean = type("boolean"); diff --git a/src/assertions/boolean/types.d.ts b/src/assertions/boolean/types.d.ts deleted file mode 100644 index be3e58a..0000000 --- a/src/assertions/boolean/types.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Type { - export type Boolean = Brand< - "type", - "boolean", - { - input: boolean; - output: boolean; - } - >; - } -} diff --git a/src/assertions/email/index.ts b/src/assertions/email/index.ts index 55ccf5f..04ef09d 100644 --- a/src/assertions/email/index.ts +++ b/src/assertions/email/index.ts @@ -1,5 +1,4 @@ import { regex } from "@assertions/regex"; -import type { Validate } from "./types"; /** * Checks if value matches email RegExp. @@ -10,4 +9,4 @@ import type { Validate } from "./types"; * email("yamiteru@icloud.com"); // passes * ``` */ -export const email = regex(/^\w+@.+\..+$/) as Validate.Regex.Email; +export const email = regex(/^\w+@.+\..+$/); diff --git a/src/assertions/email/types.d.ts b/src/assertions/email/types.d.ts deleted file mode 100644 index 1df8f98..0000000 --- a/src/assertions/email/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Regex { - export type Email = Brand<"regex", "email">; - } -} diff --git a/src/assertions/endsWith/index.ts b/src/assertions/endsWith/index.ts index 2efbdfd..72dffa5 100644 --- a/src/assertions/endsWith/index.ts +++ b/src/assertions/endsWith/index.ts @@ -1,10 +1,10 @@ import { error } from "@error"; -import type { Validate } from "./types"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if value ends with `searchString`. * - * @param searchString - The characters to be searched for at the end of value. + * @param input - The characters to be searched for at the end of value. * * @throws `endsWith` if value does not end with `searchString`. * @@ -16,9 +16,7 @@ import type { Validate } from "./types"; * question("really?"); // passes * ``` */ -export const endsWith = <$SearchString extends string>( - searchString: $SearchString, -) => - ((v: any) => - v.endsWith(searchString) || - error(endsWith)) as unknown as Validate.String.EndsWith<$SearchString>; +export const endsWith = + <$Input extends string>(input: $Input): Assertion => + (v: unknown) => + (v as any).endsWith(input) || error(endsWith); diff --git a/src/assertions/endsWith/types.d.ts b/src/assertions/endsWith/types.d.ts deleted file mode 100644 index b5ca4a7..0000000 --- a/src/assertions/endsWith/types.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace String { - export type EndsWith<$Type extends string> = Brand< - "string-endswith", - $Type - >; - } -} diff --git a/src/assertions/expect/index.ts b/src/assertions/expect/index.ts index edb89ae..9bd7e2f 100644 --- a/src/assertions/expect/index.ts +++ b/src/assertions/expect/index.ts @@ -1,11 +1,10 @@ -import type { Message } from "@assertions/expect/types"; import { error } from "@error"; -import type { AnyBrand } from "@the-minimal/types"; +import type { UnknownAssertion } from "@the-minimal/types"; /** * Wraps assertion and throws an error with message if assertion fails. * - * @param brand - Assertion to be checked. + * @param assertion - Assertion to be checked. * @param message - Message to be used in error. * * @example @@ -16,14 +15,14 @@ import type { AnyBrand } from "@the-minimal/types"; * ); * ``` */ -export const expect = <$Brand extends AnyBrand>( - brand: $Brand, - message: Message, +export const expect = <$Assertion extends UnknownAssertion>( + assertion: $Assertion, + message: (error: any, value: unknown) => string, ) => ((v: unknown) => { try { - (brand as any)(v); - } catch (e: any) { - error(brand, message(e, v)); + assertion(v); + } catch (e) { + error(assertion, message(e, v)); } - }) as unknown as $Brand; + }) as $Assertion; diff --git a/src/assertions/expect/types.d.ts b/src/assertions/expect/types.d.ts deleted file mode 100644 index 3a90119..0000000 --- a/src/assertions/expect/types.d.ts +++ /dev/null @@ -1 +0,0 @@ -export type Message = (error: any, input: unknown) => string; diff --git a/src/assertions/includes/index.ts b/src/assertions/includes/index.ts index 4bf5db6..096fa0b 100644 --- a/src/assertions/includes/index.ts +++ b/src/assertions/includes/index.ts @@ -1,5 +1,5 @@ -import type { Validate } from "@assertions/includes/types"; import { error } from "@error"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if value includes with another value. @@ -14,7 +14,7 @@ import { error } from "@error"; * hello("--hello--"); // passes * ``` */ -export const includes = (input: $Input) => - ((v: any) => - v.includes(input) || - error(includes)) as unknown as Validate.List.Includes<$Input>; +export const includes = + (input: unknown): Assertion => + (v: unknown) => + (v as any).includes(input) || error(includes); diff --git a/src/assertions/includes/types.d.ts b/src/assertions/includes/types.d.ts deleted file mode 100644 index 4c8da0f..0000000 --- a/src/assertions/includes/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace List { - export type Includes<$Input> = Brand<"list-includes", $Input>; - } -} diff --git a/src/assertions/integer/index.ts b/src/assertions/integer/index.ts index 17edfd4..0962481 100644 --- a/src/assertions/integer/index.ts +++ b/src/assertions/integer/index.ts @@ -1,5 +1,5 @@ -import type { Validate } from "@assertions/integer/types"; import { error } from "@error"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if value is integer. @@ -10,5 +10,5 @@ import { error } from "@error"; * integer(1) // passes * ``` */ -export const integer = ((v: unknown) => - Number.isInteger(v) || error(integer)) as unknown as Validate.Number.Integer; +export const integer: Assertion = (v: unknown) => + Number.isInteger(v) || error(integer); diff --git a/src/assertions/integer/types.d.ts b/src/assertions/integer/types.d.ts deleted file mode 100644 index 331d9f1..0000000 --- a/src/assertions/integer/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Number { - export type Integer = Brand<"number-integer">; - } -} diff --git a/src/assertions/isArray/index.ts b/src/assertions/isArray/index.ts index e6f81a8..90f64e0 100644 --- a/src/assertions/isArray/index.ts +++ b/src/assertions/isArray/index.ts @@ -1,5 +1,5 @@ import { error } from "@error"; -import type { Validate } from "./types"; +import type { Assertion } from "@the-minimal/types"; /** * Checks that the value is an array. @@ -10,5 +10,5 @@ import type { Validate } from "./types"; * isArray([]); // passes * ``` */ -export const isArray = ((v: unknown) => - Array.isArray(v) || error(isArray)) as unknown as Validate.Type.Array; +export const isArray: Assertion = (v: unknown) => + Array.isArray(v) || error(isArray); diff --git a/src/assertions/isArray/types.d.ts b/src/assertions/isArray/types.d.ts deleted file mode 100644 index 5950c55..0000000 --- a/src/assertions/isArray/types.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Brand, None } from "@the-minimal/types"; - -export namespace Validate { - export namespace Type { - export type Array = Brand< - "array", - None, - { - input: unknown[]; - output: None; - } - >; - } -} diff --git a/src/assertions/isObject/index.ts b/src/assertions/isObject/index.ts index a843a76..14d4040 100644 --- a/src/assertions/isObject/index.ts +++ b/src/assertions/isObject/index.ts @@ -1,8 +1,5 @@ -import type { Validate as AndValidate } from "@assertions/and/types"; -// TODO: this is fucking ugly -import type { Validate as IsObjectValidate } from "@assertions/isObject/types"; -import type { Validate as NotValueValidate } from "@assertions/notValue/types"; import { error } from "@error"; +import type { Assertion } from "@the-minimal/types"; /** * Checks that the value is of type object and is not null. @@ -14,8 +11,5 @@ import { error } from "@error"; * isObject({}); // passes * ``` */ -export const isObject = ((v: unknown) => - (v !== null && typeof v === "object") || - error(isObject)) as unknown as AndValidate.And< - [NotValueValidate.Value.Ne, IsObjectValidate.Type.Object] ->; +export const isObject: Assertion> = (v: unknown) => + (v !== null && typeof v === "object") || error(isObject); diff --git a/src/assertions/isObject/types.d.ts b/src/assertions/isObject/types.d.ts deleted file mode 100644 index 478e6f5..0000000 --- a/src/assertions/isObject/types.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { Brand, None } from "@the-minimal/types"; - -export namespace Validate { - export namespace Type { - export type Object = Brand< - "object", - None, - { - input: ObjectUnknown; - output: None; - } - >; - } -} - -export type ObjectUnknown = Record; diff --git a/src/assertions/lazy/index.ts b/src/assertions/lazy/index.ts index 1455a19..8b88a62 100644 --- a/src/assertions/lazy/index.ts +++ b/src/assertions/lazy/index.ts @@ -1,4 +1,4 @@ -import type { AnyBrand } from "@the-minimal/types"; +import type { UnknownAssertion } from "@the-minimal/types"; /** * Wraps assertion in a function that will be evaluated only when the assertion is called. @@ -20,9 +20,9 @@ import type { AnyBrand } from "@the-minimal/types"; * }); // passes * ``` */ -export const lazy = <$Validation extends AnyBrand>( - assertion: (input: unknown) => $Validation, +export const lazy = <$Assertion extends UnknownAssertion>( + assertion: $Assertion, ) => ((input: unknown) => { (assertion(input) as any)(input); - }) as unknown as $Validation; + }) as $Assertion; diff --git a/src/assertions/length/index.ts b/src/assertions/length/index.ts index bb66071..748c3ac 100644 --- a/src/assertions/length/index.ts +++ b/src/assertions/length/index.ts @@ -1,5 +1,5 @@ import { error } from "@error"; -import type { Validate } from "./types"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if length of value is equal to the provided length. @@ -14,7 +14,7 @@ import type { Validate } from "./types"; * nonEmpty("hello"); // passes * ``` */ -export const length = <$Input extends number>(input: $Input) => - ((v: any) => - v.length === input || - error(length)) as unknown as Validate.Length.Eq<$Input>; +export const length = + (input: number): Assertion => + (v: unknown) => + (v as any).length === input || error(length); diff --git a/src/assertions/length/types.d.ts b/src/assertions/length/types.d.ts deleted file mode 100644 index bd3655c..0000000 --- a/src/assertions/length/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Length { - export type Eq<$Type extends number> = Brand<"length-eq", $Input>; - } -} diff --git a/src/assertions/maxLength/index.ts b/src/assertions/maxLength/index.ts index fe44a3c..75a3425 100644 --- a/src/assertions/maxLength/index.ts +++ b/src/assertions/maxLength/index.ts @@ -1,5 +1,5 @@ import { error } from "@error"; -import type { Validate } from "./types"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if length of value is less than or equal to the provided length. @@ -14,7 +14,7 @@ import type { Validate } from "./types"; * passwordMaxLength("Test123456"); // passes * ``` */ -export const maxLength = <$Input extends number>(length: $Input) => - ((v: any) => - v.length <= length || - error(maxLength)) as unknown as Validate.Length.Max<$Input>; +export const maxLength = + (length: number): Assertion => + (v: unknown) => + (v as any).length <= length || error(maxLength); diff --git a/src/assertions/maxLength/types.d.ts b/src/assertions/maxLength/types.d.ts deleted file mode 100644 index 7a82ae4..0000000 --- a/src/assertions/maxLength/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Length { - export type Max<$Type extends number> = Brand<"length-max", $Input>; - } -} diff --git a/src/assertions/maxValue/index.ts b/src/assertions/maxValue/index.ts index 0b39d74..a9e7a31 100644 --- a/src/assertions/maxValue/index.ts +++ b/src/assertions/maxValue/index.ts @@ -1,5 +1,4 @@ import { error } from "@error"; -import type { Validate } from "./types"; /** * Checks if value is less than or equal to the provided length. @@ -14,6 +13,5 @@ import type { Validate } from "./types"; * teenagerAge(15); // passes * ``` */ -export const maxValue = (input: $Input) => - ((v: any) => - v <= input || error(maxValue)) as unknown as Validate.Value.Max<$Input>; +export const maxValue = (input: unknown) => (v: unknown) => + v <= input || error(maxValue); diff --git a/src/assertions/maxValue/types.d.ts b/src/assertions/maxValue/types.d.ts deleted file mode 100644 index 215ee14..0000000 --- a/src/assertions/maxValue/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Value { - export type Max<$Input> = Brand<"value-max", $Input>; - } -} diff --git a/src/assertions/minLength/index.ts b/src/assertions/minLength/index.ts index 27ebcaf..9769742 100644 --- a/src/assertions/minLength/index.ts +++ b/src/assertions/minLength/index.ts @@ -1,5 +1,5 @@ import { error } from "@error"; -import type { Validate } from "./types"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if length of value is greater than or equal to the provided length. @@ -14,7 +14,7 @@ import type { Validate } from "./types"; * passwordMinLength("Test123456"); // passes * ``` */ -export const minLength = <$Input extends number>(length: $Input) => - ((v: any) => - v.length >= length || - error(minLength)) as unknown as Validate.Length.Min<$Input>; +export const minLength = + (length: number): Assertion => + (v: unknown) => + (v as any).length >= length || error(minLength); diff --git a/src/assertions/minLength/types.d.ts b/src/assertions/minLength/types.d.ts deleted file mode 100644 index 097a631..0000000 --- a/src/assertions/minLength/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Length { - export type Min<$Type extends number> = Brand<"length-min", $Input>; - } -} diff --git a/src/assertions/minValue/index.ts b/src/assertions/minValue/index.ts index c784341..4727eb4 100644 --- a/src/assertions/minValue/index.ts +++ b/src/assertions/minValue/index.ts @@ -1,5 +1,5 @@ -import type { Validate } from "@assertions/minValue/types"; import { error } from "@error"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if value is greater than or equal to the provided length. @@ -14,6 +14,7 @@ import { error } from "@error"; * adultAge(26); // passes * ``` */ -export const minValue = (input: $Input) => - ((v: any) => - v >= input || error(minValue)) as unknown as Validate.Value.Min<$Input>; +export const minValue = + (input: unknown): Assertion => + (v: unknown) => + v >= input || error(minValue); diff --git a/src/assertions/minValue/types.d.ts b/src/assertions/minValue/types.d.ts deleted file mode 100644 index 09a7f19..0000000 --- a/src/assertions/minValue/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Value { - export type Min<$Input> = Brand<"value-min", $Input>; - } -} diff --git a/src/assertions/modulo/index.ts b/src/assertions/modulo/index.ts index 299e204..0c79788 100644 --- a/src/assertions/modulo/index.ts +++ b/src/assertions/modulo/index.ts @@ -1,10 +1,7 @@ -import type { Validate } from "@assertions/modulo/types"; import { error } from "@error"; +import type { Assertion } from "@the-minimal/types"; -export const modulo = <$Divider extends number, $Remainder extends number>( - divider: $Divider, - remainder: $Remainder, -) => - ((v: number) => - v % divider === remainder || - error(modulo)) as unknown as Validate.Number.Modulo<$Divider, $Remainder>; +export const modulo = + (divider: number, remainder: number): Assertion => + (v: unknown) => + v % divider === remainder || error(modulo); diff --git a/src/assertions/modulo/types.d.ts b/src/assertions/modulo/types.d.ts deleted file mode 100644 index afa9f18..0000000 --- a/src/assertions/modulo/types.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Number { - export type Modulo< - $Divider extends number, - $Remainder extends number, - > = Brand< - "number-modulo", - { - divider: $Divider; - remainder: $Remainder; - } - >; - } -} diff --git a/src/assertions/notLength/index.ts b/src/assertions/notLength/index.ts index b42e458..cf090c8 100644 --- a/src/assertions/notLength/index.ts +++ b/src/assertions/notLength/index.ts @@ -1,5 +1,5 @@ import { error } from "@error"; -import type { Validate } from "./types"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if length of value is not equal to the provided length. @@ -14,7 +14,7 @@ import type { Validate } from "./types"; * twoLetters("ab"); // passes * ``` */ -export const notLength = <$Input extends number>(length: $Input) => - ((v: any) => - v.length !== length || - error(notLength)) as unknown as Validate.Length.Ne<$Input>; +export const notLength = + (length: number): Assertion => + (v: unknown) => + (v as any).length !== length || error(notLength); diff --git a/src/assertions/notLength/types.d.ts b/src/assertions/notLength/types.d.ts deleted file mode 100644 index 648e901..0000000 --- a/src/assertions/notLength/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Length { - export type Ne<$Type extends number> = Brand<"length-ne", $Input>; - } -} diff --git a/src/assertions/notValue/index.ts b/src/assertions/notValue/index.ts index 0c46980..a4e4db4 100644 --- a/src/assertions/notValue/index.ts +++ b/src/assertions/notValue/index.ts @@ -1,5 +1,5 @@ -import type { Validate } from "@assertions/notValue/types"; import { error } from "@error"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if value is not equal to the provided value. @@ -14,6 +14,7 @@ import { error } from "@error"; * notNan(123); // passes * ``` */ -export const notValue = (input: $Input) => - ((v: unknown) => - v !== input || error(notValue)) as unknown as Validate.Value.Ne<$Input>; +export const notValue = + (input: unknown): Assertion => + (v: unknown) => + v !== input || error(notValue); diff --git a/src/assertions/notValue/types.d.ts b/src/assertions/notValue/types.d.ts deleted file mode 100644 index 40b0604..0000000 --- a/src/assertions/notValue/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Value { - export type Ne<$Input> = Brand<"value-ne", $Input>; - } -} diff --git a/src/assertions/nullable/index.ts b/src/assertions/nullable/index.ts index 2825ec5..84c094a 100644 --- a/src/assertions/nullable/index.ts +++ b/src/assertions/nullable/index.ts @@ -1,10 +1,14 @@ -import type { AnyBrand } from "@the-minimal/types"; -import type { Validate } from "./types"; +import type { + Assertion, + InferAssertion, + Nullable, + UnknownAssertion, +} from "@the-minimal/types"; /** * Checks if the assertion passes or if the value is null. * - * @param brand - Assertion to be checked. + * @param assertion - Assertion to be checked. * * @example * ```ts @@ -15,6 +19,9 @@ import type { Validate } from "./types"; * maybeString(null); // passes * ``` */ -export const nullable = <$Brand extends AnyBrand>(brand: $Brand) => - ((v: unknown) => - v === null || (brand as any)(v)) as unknown as Validate.Nullable<$Brand>; +export const nullable = + <$Assertion extends UnknownAssertion>( + assertion: $Assertion, + ): Assertion>> => + (v: unknown) => + v === null || (assertion as any)(v); diff --git a/src/assertions/nullable/types.d.ts b/src/assertions/nullable/types.d.ts deleted file mode 100644 index e88db03..0000000 --- a/src/assertions/nullable/types.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { - AnyBrand, - Brand, - Nullable as TNullable, -} from "@the-minimal/types"; -import type { InferInput } from "@types"; - -export namespace Validate { - export type Nullable<$Brand extends AnyBrand> = Brand< - "nullable", - None, - { input: TNullable>; output: None } - >; -} diff --git a/src/assertions/nullish/index.ts b/src/assertions/nullish/index.ts index f5d9a4f..2863e61 100644 --- a/src/assertions/nullish/index.ts +++ b/src/assertions/nullish/index.ts @@ -1,5 +1,9 @@ -import type { AnyBrand } from "@the-minimal/types"; -import type { Validate } from "./types"; +import type { + Assertion, + InferAssertion, + Nullish, + UnknownAssertion, +} from "@the-minimal/types"; /** * Checks if the assertion passes or if the value is null or undefined. @@ -16,8 +20,9 @@ import type { Validate } from "./types"; * maybeString(undefined); // passes * ``` */ -export const nullish = <$Brand extends AnyBrand>(brand: $Brand) => - ((v: unknown) => - v === null || - v === undefined || - (brand as any)(v)) as unknown as Validate.Nullish<$Brand>; +export const nullish = + <$Assertion extends UnknownAssertion>( + assertion: $Assertion, + ): Assertion>> => + (v: unknown) => + v === null || v === undefined || (assertion as any)(v); diff --git a/src/assertions/nullish/types.d.ts b/src/assertions/nullish/types.d.ts deleted file mode 100644 index 27728c4..0000000 --- a/src/assertions/nullish/types.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { AnyBrand, Brand, Nullish as TNullish } from "@the-minimal/types"; -import type { InferInput } from "@types"; - -export namespace Validate { - export type Nullish<$Brand extends AnyBrand> = Brand< - "nullish", - None, - { input: TNullish>; output: None } - >; -} diff --git a/src/assertions/number/index.ts b/src/assertions/number/index.ts index 5f8b54a..ae0cbaa 100644 --- a/src/assertions/number/index.ts +++ b/src/assertions/number/index.ts @@ -1,5 +1,4 @@ import { type } from "@assertions/type"; -import type { Validate } from "./types"; /** * Checks that the value is a number. @@ -10,4 +9,4 @@ import type { Validate } from "./types"; * number(1); // passes * ``` */ -export const number = type("number") as Validate.Type.Number; +export const number = type("number"); diff --git a/src/assertions/number/types.d.ts b/src/assertions/number/types.d.ts deleted file mode 100644 index 4531e80..0000000 --- a/src/assertions/number/types.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Type { - export type Number = Brand< - "type", - "number", - { - input: number; - output: number; - } - >; - } -} diff --git a/src/assertions/object/index.ts b/src/assertions/object/index.ts index d631355..f850cc5 100644 --- a/src/assertions/object/index.ts +++ b/src/assertions/object/index.ts @@ -1,5 +1,9 @@ import { isObject } from "@assertions/isObject"; -import type { General, ObjectSchema } from "@assertions/object/types"; +import type { + Assertion, + InferAssertion, + UnknownAssertion, +} from "@the-minimal/types"; /** * Checks that assertion passes for each key/value of the object. @@ -25,14 +29,18 @@ import type { General, ObjectSchema } from "@assertions/object/types"; * }); // passes * ``` */ -export const object = <$Schema extends ObjectSchema>(schema: $Schema) => { +export const object = <$Schema extends Record>( + schema: $Schema, +): Assertion<{ + [$Key in keyof $Schema]: InferAssertion<$Schema[$Key]>; +}> => { const keys = Object.keys(schema); - return ((v: any) => { - (isObject as any)(v); + return (v: unknown) => { + isObject(v); for (let i = 0; i < keys.length; ++i) { - (schema[keys[i]] as any)(v[keys[i] as any]); + (schema[keys[i]] as any)((v as any)[keys[i] as any]); } - }) as unknown as General.Object<$Schema>; + }; }; diff --git a/src/assertions/object/types.d.ts b/src/assertions/object/types.d.ts deleted file mode 100644 index 654af21..0000000 --- a/src/assertions/object/types.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { And } from "@assertions/and/types"; -import type { Regex } from "@assertions/email/types"; -import type { Type } from "@assertions/type/types"; -import type { AnyBrand, Brand } from "@the-minimal/types"; -import type { InferInput, InferOutput } from "@types"; - -export namespace General { - export type Object<$Schema extends ObjectSchema> = Brand< - "object", - any, - { - input: InferObjectInputs<$Schema>; - output: InferObjectOutputs<$Schema>; - } - >; -} - -export type ObjectSchema = Record; - -export type ObjectAny = Record; - -export type InferObjectInputs<$Types extends ObjectAny> = { - [$Key in keyof $Types]: InferInput<$Types[$Key]>; -}; - -export type InferObjectOutputs<$Types extends ObjectAny> = { - [$Key in keyof $Types]: InferOutput<$Types[$Key]>; -}; diff --git a/src/assertions/optional/index.ts b/src/assertions/optional/index.ts index 5082478..f9e6c64 100644 --- a/src/assertions/optional/index.ts +++ b/src/assertions/optional/index.ts @@ -1,10 +1,14 @@ -import type { AnyBrand } from "@the-minimal/types"; -import type { Validate } from "./types"; +import type { + Assertion, + InferAssertion, + Optional, + UnknownAssertion, +} from "@the-minimal/types"; /** * Checks if the assertion passes or if the value is undefined. * - * @param brand - Assertion to be checked. + * @param assertion - Assertion to be checked. * * @example * ```ts @@ -15,7 +19,9 @@ import type { Validate } from "./types"; * maybeString(undefined); // passes * ``` */ -export const optional = <$Brand extends AnyBrand>(brand: $Brand) => - ((v: unknown) => - v === undefined || - (brand as any)(v)) as unknown as Validate.Optional<$Brand>; +export const optional = + <$Assertion extends UnknownAssertion>( + assertion: $Assertion, + ): Assertion>> => + (v: unknown) => + v === undefined || (assertion as any)(v); diff --git a/src/assertions/optional/types.d.ts b/src/assertions/optional/types.d.ts deleted file mode 100644 index 1732c20..0000000 --- a/src/assertions/optional/types.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { - AnyBrand, - Brand, - Optional as TOptional, -} from "@the-minimal/types"; -import type { InferInput } from "@types"; - -export namespace Validate { - export type Optional<$Brand extends AnyBrand> = Brand< - "optional", - None, - { input: TOptional>; output: None } - >; -} diff --git a/src/assertions/or/index.ts b/src/assertions/or/index.ts index c7eb91c..0002133 100644 --- a/src/assertions/or/index.ts +++ b/src/assertions/or/index.ts @@ -1,5 +1,9 @@ -import type { OrSchema, Validate } from "@assertions/or/types"; import { error } from "@error"; +import type { + Assertion, + InferAssertion, + UnknownAssertion, +} from "@the-minimal/types"; /** * Checks if one of the assertions passes. @@ -8,7 +12,7 @@ import { error } from "@error"; * * If you have two or three assertions consider using {@link or2} or {@link or3} respectively. * - * @param validations - Array of assertions to be checked + * @param assertions - Array of assertions to be checked * * @example * ```ts @@ -21,16 +25,21 @@ import { error } from "@error"; * trueish("yes"); // passes * ``` */ -export const or = ( - validations: $Validations, -) => - ((v: unknown) => { - for (let i = 0; i < validations.length; ++i) { +export const or = + ( + assertions: $Assertions, + ): Assertion< + { + [$Key in keyof $Assertions]: InferAssertion<$Assertions[$Key]>; + }[number] + > => + (v: unknown) => { + for (let i = 0; i < assertions.length; ++i) { try { - (validations[i] as any)(v); + (assertions[i] as any)(v); return; } catch {} } error(or); - }) as unknown as Validate.Or<$Validations>; + }; diff --git a/src/assertions/or/types.d.ts b/src/assertions/or/types.d.ts deleted file mode 100644 index b2cadcd..0000000 --- a/src/assertions/or/types.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { - AnyBrand, - Assertion, - Brand, - InferAssertion, - None, - UnknownAssertion, -} from "@the-minimal/types"; - -export namespace Validate { - export type Or<$Schema extends OrSchema> = Brand< - "or", - $Schema, - { - input: InferOrSchema<$Schema>[number]; - output: None; - } - >; -} - -export type OrSchema = AnyBrand[]; - -export type InferOrSchema<$Schema extends OrSchema> = { - [$Key in keyof $Schema]: InferInput<$Schema[$Key]>; -}; diff --git a/src/assertions/or2/index.ts b/src/assertions/or2/index.ts index 1402d49..52842a1 100644 --- a/src/assertions/or2/index.ts +++ b/src/assertions/or2/index.ts @@ -1,5 +1,8 @@ -import type { Validate } from "@assertions/or/types"; -import type { AnyBrand } from "@the-minimal/types"; +import type { + Assertion, + InferAssertion, + UnknownAssertion, +} from "@the-minimal/types"; /** * Checks if one of two assertions passes. @@ -19,14 +22,15 @@ import type { AnyBrand } from "@the-minimal/types"; * trueish("true"); // passes * ``` */ -export const or2 = <$Brand1 extends AnyBrand, $Brand2 extends AnyBrand>( - brand1: $Brand1, - brand2: $Brand2, -) => - ((v: unknown) => { +export const or2 = + <$Assertion1 extends UnknownAssertion, $Assertion2 extends UnknownAssertion>( + assertion1: $Assertion1, + assertion2: $Assertion2, + ): Assertion | InferAssertion<$Assertion2>> => + (v: unknown) => { try { - (brand1 as any)(v); + assertion1(v); } catch { - (brand2 as any)(v); + assertion2(v); } - }) as unknown as Validate.Or<[$Brand1, $Brand2]>; + }; diff --git a/src/assertions/or3/index.ts b/src/assertions/or3/index.ts index a80de6f..b2fd5b4 100644 --- a/src/assertions/or3/index.ts +++ b/src/assertions/or3/index.ts @@ -1,14 +1,17 @@ -import type { Validate } from "@assertions/or/types"; -import type { AnyBrand } from "@the-minimal/types"; +import type { + Assertion, + InferAssertion, + UnknownAssertion, +} from "@the-minimal/types"; /** * Checks if one of two assertions passes. * * If none of them passes it throws an error. * - * @param brand1 - First assertion to be checked. - * @param brand2 - Second assertion to be checked. - * @param brand3 - Third assertion to be checked. + * @param assertion1 - First assertion to be checked. + * @param assertion2 - Second assertion to be checked. + * @param assertion2 - Third assertion to be checked. * * @example * ```ts @@ -19,23 +22,28 @@ import type { AnyBrand } from "@the-minimal/types"; * trueish(true); // passes * ``` */ -export const or3 = < - $Brand1 extends AnyBrand, - $Brand2 extends AnyBrand, - $Brand3 extends AnyBrand, ->( - brand1: $Brand1, - brand2: $Brand2, - brand3: $Brand3, -) => - ((v: unknown) => { +export const or3 = + < + $Assertion1 extends UnknownAssertion, + $Assertion2 extends UnknownAssertion, + $Assertion3 extends UnknownAssertion, + >( + assertion1: $Assertion1, + assertion2: $Assertion2, + assertion3: $Assertion3, + ): Assertion< + | InferAssertion<$Assertion1> + | InferAssertion<$Assertion2> + | InferAssertion<$Assertion3> + > => + (v: unknown) => { try { - (brand1 as any)(v); + assertion1(v); } catch { try { - (brand2 as any)(v); + assertion2(v); } catch { - (brand3 as any)(v); + assertion3(v); } } - }) as unknown as Validate.Or<[$Brand1, $Brand2, $Brand3]>; + }; diff --git a/src/assertions/rangeLength/index.ts b/src/assertions/rangeLength/index.ts index 131b3f4..ca2f2e9 100644 --- a/src/assertions/rangeLength/index.ts +++ b/src/assertions/rangeLength/index.ts @@ -1,5 +1,5 @@ import { error } from "@error"; -import type { Validate } from "./types"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if length of value is in the range of min and max. @@ -16,10 +16,8 @@ import type { Validate } from "./types"; * passwordLength("Test123456"); // passes * ``` */ -export const rangeLength = <$Min extends number, $Max extends number>( - min: $Min, - max: $Max, -) => - ((v: any) => - (v.length >= min && v.length <= max) || - error(rangeLength)) as unknown as Validate.Length.Range<$Min, $Max>; +export const rangeLength = + (min: number, max: number): Assertion => + (v: unknown) => + ((v as any).length >= min && (v as any).length <= max) || + error(rangeLength); diff --git a/src/assertions/rangeLength/types.d.ts b/src/assertions/rangeLength/types.d.ts deleted file mode 100644 index fde9de0..0000000 --- a/src/assertions/rangeLength/types.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Length { - export type Range<$Min extends number, $Max extends number> = Brand< - "length-range", - { - min: $Min; - max: $Max; - } - >; - } -} diff --git a/src/assertions/rangeValue/index.ts b/src/assertions/rangeValue/index.ts index 00b1d8f..b4e600b 100644 --- a/src/assertions/rangeValue/index.ts +++ b/src/assertions/rangeValue/index.ts @@ -1,5 +1,5 @@ -import type { Validate } from "@assertions/rangeValue/types"; import { error } from "@error"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if value is in the range of min and max. @@ -16,7 +16,7 @@ import { error } from "@error"; * alive(26); // passes * ``` */ -export const rangeValue = (min: $Min, max: $Max) => - ((v: any) => - (v >= min && v <= max) || - error(rangeValue)) as unknown as Validate.Value.Range<$Min, $Max>; +export const rangeValue = + <$Min, $Max extends $Min>(min: $Min, max: $Max): Assertion => + (v: unknown) => + (v >= min && v <= max) || error(rangeValue); diff --git a/src/assertions/rangeValue/types.d.ts b/src/assertions/rangeValue/types.d.ts deleted file mode 100644 index 4dbc0fb..0000000 --- a/src/assertions/rangeValue/types.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Value { - export type Range<$Min, $Max> = Brand< - "value-range", - { min: $Min; max: $Max } - >; - } -} diff --git a/src/assertions/regex/index.ts b/src/assertions/regex/index.ts index 5bf0f2e..79b9353 100644 --- a/src/assertions/regex/index.ts +++ b/src/assertions/regex/index.ts @@ -1,5 +1,5 @@ import { error } from "@error"; -import type { Validate } from "./types"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if value matches regex pattern. @@ -14,6 +14,7 @@ import type { Validate } from "./types"; * email("123"); // passes * ``` */ -export const regex = (pattern: RegExp) => - ((v: string) => - pattern.test(v) || error(regex)) as unknown as Validate.Regex.Any; +export const regex = + (pattern: RegExp): Assertion => + (v: unknown) => + pattern.test(v as string) || error(regex); diff --git a/src/assertions/regex/types.d.ts b/src/assertions/regex/types.d.ts deleted file mode 100644 index 1db763f..0000000 --- a/src/assertions/regex/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Regex { - export type Any = Brand<"regex", any, any>; - } -} diff --git a/src/assertions/startsWith/index.ts b/src/assertions/startsWith/index.ts index 78e2cb7..8c1e9fd 100644 --- a/src/assertions/startsWith/index.ts +++ b/src/assertions/startsWith/index.ts @@ -1,10 +1,10 @@ -import type { Validate } from "@assertions/startsWith/types"; import { error } from "@error"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if value starts with `searchString`. * - * @param searchString - The characters to be searched for at the start of value. + * @param input - The characters to be searched for at the start of value. * * @throws `startsWith` if value does not start with `searchString`. * @@ -16,9 +16,7 @@ import { error } from "@error"; * startsWithId("ID: 123"); // passes * ``` */ -export const startsWith = <$SearchString extends string>( - searchString: $SearchString, -) => - ((v: any) => - v.startsWith(searchString) || - error(startsWith)) as unknown as Validate.String.StartsWith<$SearchString>; +export const startsWith = + (input: string): Assertion => + (v: unknown) => + (v as string).startsWith(input) || error(startsWith); diff --git a/src/assertions/startsWith/types.d.ts b/src/assertions/startsWith/types.d.ts deleted file mode 100644 index 843f5d3..0000000 --- a/src/assertions/startsWith/types.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace String { - export type StartsWith<$Input extends string> = Brand< - "string-startswith", - $Input - >; - } -} diff --git a/src/assertions/string/index.ts b/src/assertions/string/index.ts index 171f57f..a835024 100644 --- a/src/assertions/string/index.ts +++ b/src/assertions/string/index.ts @@ -1,5 +1,4 @@ import { type } from "@assertions/type"; -import type { Validate } from "./types"; /** * Checks that the value is a string. @@ -10,4 +9,4 @@ import type { Validate } from "./types"; * string("hello"); // passes * ``` */ -export const string = type("string") as Validate.Type.String; +export const string = type("string"); diff --git a/src/assertions/string/types.d.ts b/src/assertions/string/types.d.ts deleted file mode 100644 index 00a1677..0000000 --- a/src/assertions/string/types.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Type { - export type String = Brand< - "type", - "string", - { - input: string; - output: string; - } - >; - } -} diff --git a/src/assertions/tuple/index.ts b/src/assertions/tuple/index.ts index 8896dae..5ba4f6c 100644 --- a/src/assertions/tuple/index.ts +++ b/src/assertions/tuple/index.ts @@ -1,5 +1,9 @@ import { isArray } from "@assertions/isArray"; -import type { TupleSchema, Validate } from "./types"; +import type { + Assertion, + InferAssertion, + UnknownAssertion, +} from "@the-minimal/types"; /** * Checks that assertion passes for each element of the tuple. @@ -15,11 +19,16 @@ import type { TupleSchema, Validate } from "./types"; * position([1, 2]) // passes * ``` */ -export const tuple = (assertions: $Schema) => - ((v: any) => { - (isArray as any)(v); +export const tuple = + ( + assertions: $Assertions, + ): Assertion<{ + [$Key in keyof $Assertions]: InferAssertion<$Assertions[$Key]>; + }> => + (v: unknown) => { + isArray(v); for (let i = 0; i < assertions.length; ++i) { (assertions[i] as any)(v[i]); } - }) as unknown as Validate.Tuple<$Schema>; + }; diff --git a/src/assertions/tuple/types.d.ts b/src/assertions/tuple/types.d.ts deleted file mode 100644 index 7de668f..0000000 --- a/src/assertions/tuple/types.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { AnyBrand, Brand, None } from "@the-minimal/types"; -import type { InferInput } from "@types"; - -export namespace Validate { - export type Tuple<$Schema extends TupleSchema> = Brand< - "tuple", - $Schema, - { - input: InferTupleSchema<$Schema>; - output: None; - } - >; -} - -export type TupleSchema = AnyBrand[]; - -export type InferTupleSchema<$Schema extends TupleSchema> = { - [$Key in keyof $Schema]: InferInput<$Schema[$Key]>; -}; diff --git a/src/assertions/type/index.ts b/src/assertions/type/index.ts index e5df71d..70209fd 100644 --- a/src/assertions/type/index.ts +++ b/src/assertions/type/index.ts @@ -1,5 +1,5 @@ import { error } from "@error"; -import type { Validate } from "./types"; +import type { Assertion } from "@the-minimal/types"; /** * Checks that the value is of the provided type. @@ -14,6 +14,7 @@ import type { Validate } from "./types"; * string("hello"); // passes * ``` */ -export const type = (input: string) => - ((v: unknown) => - typeof v === input || error(type)) as unknown as Validate.Type.Any; +export const type = + <$Type>(input: string): Assertion<$Type> => + (v: unknown) => + typeof v === input || error(type); diff --git a/src/assertions/type/types.d.ts b/src/assertions/type/types.d.ts deleted file mode 100644 index 21b56be..0000000 --- a/src/assertions/type/types.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Brand } from "@the-minimal/types"; - -export namespace Validate { - export namespace Type { - export type Any = Brand< - "type", - any, - { - input: any; - output: any; - } - >; - } -} diff --git a/src/assertions/union/index.ts b/src/assertions/union/index.ts index 0bf6743..41d7c8d 100644 --- a/src/assertions/union/index.ts +++ b/src/assertions/union/index.ts @@ -1,5 +1,5 @@ import { error } from "@error"; -import type { UnionSchema, Validate } from "./types"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if the value is one of the provided options. @@ -15,6 +15,9 @@ import type { UnionSchema, Validate } from "./types"; * userRole("user"); // passes * ``` */ -export const union = (options: $Schema) => - ((v: unknown) => - options.includes(v) || error(union)) as unknown as Validate.Union<$Schema>; +export const union = + ( + options: $Options, + ): Assertion<$Options[number]> => + (v: unknown) => + options.includes(v) || error(union); diff --git a/src/assertions/union/types.d.ts b/src/assertions/union/types.d.ts deleted file mode 100644 index fe60596..0000000 --- a/src/assertions/union/types.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { AnyBrand, Brand, None } from "@the-minimal/types"; -import type { InferInput } from "@types"; - -export namespace Validate { - export type Union<$Schema extends UnionSchema> = Brand< - "union", - $Schema, - { - input: $Schema[number]; - output: None; - } - >; -} - -export type UnionSchema = unknown[]; diff --git a/src/assertions/value/index.test-d.ts b/src/assertions/value/index.test-d.ts index 80983b0..c5545c6 100644 --- a/src/assertions/value/index.test-d.ts +++ b/src/assertions/value/index.test-d.ts @@ -1,6 +1,5 @@ import { value } from "@assertions/value"; -import type { Value } from "@assertions/value/types"; import type { Assertion } from "@the-minimal/types"; import { assertType } from "vitest"; -assertType>>(value(2)); +assertType>(value(2)); diff --git a/src/assertions/value/index.ts b/src/assertions/value/index.ts index 8457aa9..bad5704 100644 --- a/src/assertions/value/index.ts +++ b/src/assertions/value/index.ts @@ -1,5 +1,5 @@ -import type { Validate } from "@assertions/value/types"; import { error } from "@error"; +import type { Assertion } from "@the-minimal/types"; /** * Checks if value is equal to the provided value. @@ -14,6 +14,7 @@ import { error } from "@error"; * isNull(null); // passes * ``` */ -export const value = (input: $Input) => - ((v: unknown) => - v === input || error(value)) as unknown as Validate.Value.Eq<$Input>; +export const value = + (input: $Input): Assertion<$Input> => + (v: unknown) => + v === input || error(value); diff --git a/src/assertions/value/types.d.ts b/src/assertions/value/types.d.ts deleted file mode 100644 index c5da798..0000000 --- a/src/assertions/value/types.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Brand, None } from "@the-minimal/types"; - -export namespace Validate { - export namespace Value { - export type Eq<$Input> = Brand< - "value-eq", - $Input, - { - input: $Input; - output: None; - } - >; - } -} diff --git a/src/types.ts b/src/types.ts index 99f328a..11cc491 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,23 +1 @@ -import type { Brand } from "@the-minimal/types"; - -export type InferInput<$Value> = $Value extends Brand< - any, - any, - { - input: infer $Type; - output: any; - } -> - ? $Type - : $Value; - -export type InferOutput<$Value> = $Value extends Brand< - any, - any, - { - input: any; - output: infer $Type; - } -> - ? $Type - : $Value; +export type { InferAssertion as Infer } from "@the-minimal/types"; diff --git a/src/utils.ts b/src/utils.ts index d52df51..627e608 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,25 +1,28 @@ -import type { AnyBrand } from "@the-minimal/types"; -import type { InferOutput } from "@types"; +import type { UnknownAssertion } from "@the-minimal/types"; +import type { Infer } from "@types"; -export function assert<$Brand extends AnyBrand>( - brand: $Brand, +export function assert<$Assertion extends UnknownAssertion>( + assertion: $Assertion, value: unknown, -): asserts value is InferOutput<$Brand> { - (brand as any)(value); +): asserts value is Infer<$Assertion> { + (assertion as any)(value); } -export function parse<$Brand extends AnyBrand>(brand: $Brand, value: unknown) { - (brand as any)(value); +export function parse<$Assertion extends UnknownAssertion>( + assertion: $Assertion, + value: unknown, +) { + (assertion as any)(value); - return value as InferOutput<$Brand>; + return value as Infer<$Assertion>; } -export function is<$Brand extends AnyBrand>( - brand: $Brand, +export function is<$Assertion extends UnknownAssertion>( + assertion: $Assertion, value: unknown, -): value is InferOutput<$Brand> { +): value is Infer<$Assertion> { try { - (brand as any)(value); + (assertion as any)(value); return true; } catch {