Skip to content

Commit

Permalink
feat(types): add reporter interface
Browse files Browse the repository at this point in the history
  • Loading branch information
TomokiMiyauci committed May 19, 2023
1 parent 59b72d3 commit 42a1238
Showing 1 changed file with 70 additions and 7 deletions.
77 changes: 70 additions & 7 deletions types.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,41 @@
// Copyright 2023-latest Tomoki Miyauchi. All rights reserved. MIT license.
// This module is browser compatible.

import { isString } from "./deps.ts";

/** Validator API. */
export interface Validator<In = unknown> {
export interface Validator<In = unknown> extends Display {
/** Validates the input and yield validation errors if exists. */
validate: (input: In) => Iterable<ValidationError>;
}

export type Validation<In = unknown, In_ extends In = In> = In extends In_
? Validator<In>
: AssertiveValidator<In, In_>;

export interface Display {
toString(): string;
}

export interface Transformer<In = unknown, Out = In> {
transform: (input: In) => Out;
}

export interface Struct<In = unknown, In_ extends In = In, Out = unknown>
extends Iterable<Validator<In> | Transformer<In, Out>> {
}

/** Assert API for validated data type. */
export interface Assert<In = unknown, Out extends In = In> {
[Assert.symbol]: Out;
export interface Assert<T = unknown> {
[Assert.symbol]: T;
}

export class Assert {
static readonly symbol = Symbol("assert.type");
static readonly symbol: unique symbol;
}

export interface AssertiveValidator<In = unknown, Out extends In = In>
extends Assert<In, Out>, Validator<In> {}
export interface AssertiveValidator<In = unknown, In_ extends In = In>
extends Validator<In>, Assert<In_> {}

/** Validation error options. */
export interface ValidationErrorOptions extends ErrorOptions {
Expand All @@ -41,8 +59,33 @@ export class ValidationError extends Error {
}
}

export interface Reporter<T = unknown> {
report(context: T): string;

expect(message: string): this;
expect(report: Reporter["report"]): this;
}

export class Reporter<T = unknown> {
#messageFn?: Reporter<T>["report"];

report(context: T): string {
return this.#messageFn?.(context) ?? "";
}

expect(messageOrReport: string | Reporter<T>["report"]): this {
const fn = isString(messageOrReport)
? (() => messageOrReport) as Reporter<T>["report"]
: messageOrReport;

this.#messageFn = fn;

return this;
}
}

/** Result of OK API. */
export class Ok<T> {
export class Ok<T = unknown> {
/** Node type. */
type: "ok" = "ok";

Expand All @@ -52,6 +95,16 @@ export class Ok<T> {
constructor(data: T) {
this.data = data;
}

/** Whether the {@link Result} is {@link Ok} or not. */
isOk(): this is Ok<T> {
return true;
}

/** Whether the {@link Result} is {@link Err} or not. */
isErr(): this is Err {
return false;
}
}

/** Result of Error API. */
Expand All @@ -65,6 +118,16 @@ export class Err {
constructor(errors: readonly ValidationError[]) {
this.errors = errors;
}

/** Whether the {@link Result} is {@link Ok} or not. */
isOk(): this is Ok {
return false;
}

/** Whether the {@link Result} is {@link Err} or not. */
isErr(): this is Err {
return true;
}
}

/** Represent {@link Ok} or {@link Err}. */
Expand Down

0 comments on commit 42a1238

Please sign in to comment.