Comparing version 0.1.5 to 0.1.6
@@ -1,2 +0,1 @@ | ||
import { array } from "./array"; | ||
import { boolean } from "./boolean"; | ||
@@ -6,2 +5,3 @@ import { lazy } from "./lazy"; | ||
import { string } from "./string"; | ||
import { array } from "./Type"; | ||
export var Flaw; | ||
@@ -8,0 +8,0 @@ (function (Flaw) { |
export { any } from "./any"; | ||
export { array } from "./array"; | ||
export { boolean } from "./boolean"; | ||
@@ -15,3 +14,3 @@ export { Flaw } from "./Flaw"; | ||
export { tuple } from "./tuple"; | ||
export { Type } from "./Type"; | ||
export { Type, array } from "./Type"; | ||
export { union } from "./union"; |
export { any } from "./any"; | ||
export { array } from "./array"; | ||
export { boolean } from "./boolean"; | ||
@@ -15,4 +14,4 @@ export { Flaw } from "./Flaw"; | ||
export { tuple } from "./tuple"; | ||
export { Type } from "./Type"; | ||
export { Type, array } from "./Type"; | ||
export { union } from "./union"; | ||
//# sourceMappingURL=isly.js.map |
@@ -9,2 +9,3 @@ import { Flaw } from "./Flaw"; | ||
readonly(): Type<Readonly<T>>; | ||
array(...options: array.Option[]): Type<T[]>; | ||
constructor(_name: string | (() => string), _condition?: string | (() => string | undefined) | undefined); | ||
@@ -54,1 +55,27 @@ /** | ||
} | ||
export declare namespace array { | ||
type Criteria = "length" | "minLength" | "maxLength"; | ||
type Option<C extends Criteria = Criteria> = { | ||
criteria: C; | ||
value: OptionValue<C>; | ||
}; | ||
} | ||
/** | ||
* Possible to have custom type for every Criteria. | ||
* Add option types with: | ||
* `C extends "myNewCriteria" ? optionTypeOfMyNewCriteria : number` | ||
*/ | ||
type OptionValue<C extends array.Criteria> = C extends array.Criteria ? number : never; | ||
export declare function array<T extends any[] = never>(itemType: Type<T[number]>, ...options: array.Option[]): Type<T>; | ||
export declare function array<I>(itemType: Type<I>, ...options: array.Option[]): Type<I[]>; | ||
export declare class IslyArray<T extends any[]> extends Type<T> { | ||
protected readonly itemType: Type<T[number]>; | ||
protected readonly options: array.Option[]; | ||
constructor(itemType: Type<T[number]>, options: array.Option[]); | ||
protected baseName(): string; | ||
protected itemName(index: number): string; | ||
is: Type.IsFunction<T>; | ||
createFlaw(value: any): Omit<Flaw, "isFlaw" | "type" | "condition">; | ||
protected getValue(value: T): T; | ||
} | ||
export {}; |
@@ -14,2 +14,5 @@ export class Type { | ||
} | ||
array(...options) { | ||
return array(this, ...options); | ||
} | ||
constructor(_name, _condition) { | ||
@@ -86,2 +89,49 @@ this._name = _name; | ||
} | ||
export function array(itemType, ...options) { | ||
return new IslyArray(itemType, options); | ||
} | ||
const criteriaFunctions = { | ||
length: { | ||
is: (value, optionValue) => value.length == optionValue, | ||
condition: optionValue => `length == ${optionValue}`, | ||
}, | ||
minLength: { | ||
is: (value, optionValue) => value.length >= optionValue, | ||
condition: optionValue => `minLength == ${optionValue}`, | ||
}, | ||
maxLength: { | ||
is: (value, optionValue) => value.length <= optionValue, | ||
condition: optionValue => `maxLength == ${optionValue}`, | ||
}, | ||
}; | ||
export class IslyArray extends Type { | ||
constructor(itemType, options) { | ||
super(() => this.baseName() + "[]", options.length > 0 ? options.map(c => criteriaFunctions[c.criteria].condition(c.value)).join(" & ") : undefined); | ||
this.itemType = itemType; | ||
this.options = options; | ||
this.is = (value => globalThis.Array.isArray(value) && | ||
this.options.every(option => criteriaFunctions[option.criteria].is(value, option.value)) && | ||
value.every(item => this.itemType.is(item))); | ||
} | ||
baseName() { | ||
return this.itemType.name.includes(" ") ? `(${this.itemType.name})` : this.itemType.name; | ||
} | ||
itemName(index) { | ||
return `${this.baseName()}[${index}]`; | ||
} | ||
createFlaw(value) { | ||
const flaws = (globalThis.Array.isArray(value) && | ||
value.flatMap((item, index) => { | ||
const subFlaw = this.itemType.flaw(item); | ||
return subFlaw.isFlaw ?? true ? [{ ...subFlaw, type: this.itemName(index) }] : []; | ||
})) || | ||
[]; | ||
return { | ||
...(flaws.length > 0 ? { flaws } : undefined), | ||
}; | ||
} | ||
getValue(value) { | ||
return value.map(item => this.itemType.get(item)); | ||
} | ||
} | ||
//# sourceMappingURL=Type.js.map |
@@ -1,2 +0,1 @@ | ||
import { array } from "./array" | ||
import { boolean } from "./boolean" | ||
@@ -6,3 +5,3 @@ import { lazy } from "./lazy" | ||
import { string } from "./string" | ||
import { Type } from "./Type" | ||
import { array, Type } from "./Type" | ||
@@ -9,0 +8,0 @@ export interface Flaw { |
export { any } from "./any" | ||
export { array } from "./array" | ||
export { boolean } from "./boolean" | ||
@@ -15,3 +14,3 @@ export { Flaw } from "./Flaw" | ||
export { tuple } from "./tuple" | ||
export { Type } from "./Type" | ||
export { Type, array } from "./Type" | ||
export { union } from "./union" |
{ | ||
"name": "isly", | ||
"version": "0.1.5", | ||
"version": "0.1.6", | ||
"description": "Library for type checking.", | ||
@@ -5,0 +5,0 @@ "author": "Utily Contributors", |
77
Type.ts
@@ -16,2 +16,5 @@ import { Flaw } from "./Flaw" | ||
} | ||
public array(...options: array.Option[]): Type<T[]> { | ||
return array(this, ...options) as any | ||
} | ||
constructor( | ||
@@ -105,1 +108,75 @@ protected readonly _name: string | (() => string), | ||
} | ||
// Array has to be here to avoid circular dependency | ||
export namespace array { | ||
export type Criteria = "length" | "minLength" | "maxLength" | ||
export type Option<C extends Criteria = Criteria> = { criteria: C; value: OptionValue<C> } | ||
} | ||
/** | ||
* Possible to have custom type for every Criteria. | ||
* Add option types with: | ||
* `C extends "myNewCriteria" ? optionTypeOfMyNewCriteria : number` | ||
*/ | ||
type OptionValue<C extends array.Criteria> = C extends array.Criteria ? number : never | ||
// The overloaded function is to avoid resulting in an Type<any[]>, but still be able to do array<number[]>(...) with only one generic! | ||
// Thanks to @jcalz at StackOverflow! | ||
// https://stackoverflow.com/questions/75128444/force-type-argument-inference-not-to-use-any-for-an-array-typescript?noredirect=1#comment132590506_75128444 | ||
export function array<T extends any[] = never>(itemType: Type<T[number]>, ...options: array.Option[]): Type<T> | ||
export function array<I>(itemType: Type<I>, ...options: array.Option[]): Type<I[]> | ||
export function array<T extends any[]>(itemType: Type<T[number]>, ...options: array.Option[]): Type<T> { | ||
return new IslyArray(itemType, options) | ||
} | ||
const criteriaFunctions: { | ||
[K in array.Criteria]: { | ||
is: (value: any[], optionValue: OptionValue<K>) => boolean | ||
condition: (optionValue: OptionValue<K>) => string | ||
} | ||
} = { | ||
length: { | ||
is: (value: any[], optionValue: number) => value.length == optionValue, | ||
condition: optionValue => `length == ${optionValue}`, | ||
}, | ||
minLength: { | ||
is: (value: any[], optionValue: number) => value.length >= optionValue, | ||
condition: optionValue => `minLength == ${optionValue}`, | ||
}, | ||
maxLength: { | ||
is: (value: any[], optionValue: number) => value.length <= optionValue, | ||
condition: optionValue => `maxLength == ${optionValue}`, | ||
}, | ||
} | ||
export class IslyArray<T extends any[]> extends Type<T> { | ||
constructor(protected readonly itemType: Type<T[number]>, protected readonly options: array.Option[]) { | ||
super( | ||
() => this.baseName() + "[]", | ||
options.length > 0 ? options.map(c => criteriaFunctions[c.criteria].condition(c.value)).join(" & ") : undefined | ||
) | ||
} | ||
protected baseName() { | ||
return this.itemType.name.includes(" ") ? `(${this.itemType.name})` : this.itemType.name | ||
} | ||
protected itemName(index: number) { | ||
return `${this.baseName()}[${index}]` | ||
} | ||
is = (value => | ||
globalThis.Array.isArray(value) && | ||
this.options.every(option => criteriaFunctions[option.criteria].is(value, option.value)) && | ||
value.every(item => this.itemType.is(item))) as Type.IsFunction<T> | ||
createFlaw(value: any): Omit<Flaw, "isFlaw" | "type" | "condition"> { | ||
const flaws = | ||
(globalThis.Array.isArray(value) && | ||
value.flatMap((item, index) => { | ||
const subFlaw = this.itemType.flaw(item) | ||
return subFlaw.isFlaw ?? true ? [{ ...subFlaw, type: this.itemName(index) }] : [] | ||
})) || | ||
[] | ||
return { | ||
...(flaws.length > 0 ? { flaws } : undefined), | ||
} | ||
} | ||
protected getValue(value: T) { | ||
return value.map(item => this.itemType.get(item)) as T | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
84051
1382
82