The @perfective/common/object package provides functions to work with the standard JS
Object class.
-
Types:
-
ObjectWithDefined<T, K extends keyof T>— an object of typeTwith a defined value of propertyK. -
ObjectWithUndefined<T, K extends keyof T>— an object of typeTwith an undefined value of propertyK. -
ObjectWithNotNull<T, K extends keyof T>— an object of typeTwith a non-null value of propertyK. -
ObjectWithNull<T, K extends keyof T>— an object of typeTwith a null value of propertyK. -
ObjectWithPresent<T, K extends keyof T>— an object of typeTwith a present value of propertyK. -
ObjectWithAbsent<T, K extends keyof T>— an object of typeTwith an absent value of propertyK. -
RecursivePartial<T>— a generic type that recursively marks all properties of a given typeTas optional. -
Entry<K = string, V = unknown>— a key-value pair (array).
-
-
Constructors:
-
recordFromArray(array: string[]): Record<string, number>— creates an object from a given array with the array values as keys and their indexes as values. -
recordFromEntries(entries: Entry[]): Record<string, unknown>— creates an object from a given array of entries. An inverse forObject.entries(). -
pick<T, K extends keyof T>(record: NonNullable<T>, …properties: readonly K[]): Pick<T, K>— creates a copy of a givenrecordonly with givenproperties. -
recordWithPicked<T, K extends keyof T>(…properties: readonly K[]): Unary<NonNullable<T>, Pick<T, K>>— creates a function topick()givenpropertiesfrom its argument. -
omit<T, K extends keyof T>(record: NonNullable<T>, …properties: readonly K[]): Omit<T, K>— creates a copy of a givenrecordwithout givenproperties. -
recordWithOmitted<T, K extends keyof T>(…property: readonly K[]): Unary<NonNullable<T>, Omit<T, K>>— creates a function toomit()givenpropertiesfrom its argument. -
filter<T, K extends keyof T>(record: NonNullable<T>, condition: Predicate<T[K]>): Partial<T>— creates a copy of a givenrecordonly with properties that meet a givencondition. -
recordFiltered<T, K extends keyof T = keyof T>(condition: Predicate<T[K]>): Unary<NonNullable<T>, Partial<T>>— creates a function tofilter()properties that satisfy a givenconditionfrom its argument. -
assigned<T, V = Partial<T>>(value: T, …overrides: (V | Partial<T>)[]): T & V— creates a shallow copy of the given value with the given overrides. -
function recordWithAssigned<T, V = Partial<T>>(…overrides: (V | Partial<T>)[]): (value: T) ⇒ T & V— creates a function to assign givenoverridesto its argument.
-
-
Type guards:
-
hasDefinedProperty<T, K extends keyof T>(property: K, …properties: readonly K[]): (value: T) ⇒ value is ObjectWithDefined<T, K>— returns a type guard that returnstrueif its argument has a definedpropertyand all givenproperties. -
hasUndefinedProperty<T, K extends keyof T>(property: K, …properties: readonly K[]): (value: T) ⇒ value is ObjectWithUndefined<T, K>— returns a type guard that returnstrueif its argument has an undefinedpropertyand all givenproperties. -
hasNotNullProperty<T, K extends keyof T>(property: K, …properties: readonly K[]): (value: T) ⇒ value is ObjectWithNotNull<T, K>— returns a type guard that returnstrueif its argument has a non-nullpropertyand all givenproperties. -
hasNullProperty<T, K extends keyof T>(property: K, …properties: readonly K[]): (value: T) ⇒ value is ObjectWithNull<T, K>— returns a type guard that returnstrueif its argument has a nullpropertyand all givenproperties. -
hasPresentProperty<T, K extends keyof T>(property: K, …properties: readonly K[]): (value: T) ⇒ value is ObjectWithPresent<T, K>— returns a type guard that returnstrueif its argument has a presentpropertyand all givenproperties. -
hasAbsentProperty<T, K extends keyof T>(property: K, …properties: readonly K[]): (value: T) ⇒ value is ObjectWithAbsent<T, K>— returns a type guard that returnstrueif its argument has an absentpropertyand all givenproperties.
-
-
Predicates:
-
isObject<T>(value: T | null): boolean— returnstruewhen the value is not null and is not a primitive. -
isRecord<T>(value: T): boolean— returnstruewhen the value is an object created from theObjectclass (not anArray,Date, etc.). -
isEmpty<T>(value: T): boolean— returnstruewhen the value is falsy, an empty array or aRecordwithout properties. -
hasMethod(value: unknown, method: string): boolean— returnstruewhen a given value implements a givenmethod. -
hasNoMethod(value: unknown, method: string): boolean— returnstruewhen a given value implements a givenmethod.
-
-
Reducers:
-
toRecordFromEntries(record: Record<string, unknown>, value: Entry): Record<string, unknown>— a reducer to build a record from entries.
-
-
Property functions:
-
property<T, K extends keyof T>(property: K): Unary<T, T[K]>— creates a function that for a given value returns the value of a givenproperty. -
property<T, K extends keyof T>(property: K, condition: Predicate<T[K]>): Predicate<T>— creates a predicate that for a given value returnstrueif a givenpropertysatisfies a givencondition. -
by<T, K extends keyof T>(property: K, order: Compare<T[K]>): Compare<T>— returns a function to compare two objects by theirpropertywith a givenordercallback.
-
One of the challenges in API development is declaring type of requests (inputs).
On the client side these types need to be as strict as possible
(e.g., all fields that are required must be marked as required).
On the server side the same type need to be treated as completely unknown, unvalidated data.
If the type is written for the client side, compiler will not be able to enforce any checks on the server side.
At the same time, server side cannot just use the plain unknown type,
as any access to properties will be prohibited (with strict compiler settings).
To resolve this issue, the Input<T> type is introduced.
It recursively adds unknown, null, and undefined to the type of every field or value.
That allows to enforce validation of input data,
while declaring the original type T can be declared in strict mode for the client side.
Validation functions and additional input types cover default JSON types:
object, array, string, number, boolean, and null.
-
Types:
-
Input<T> -
InputArray<T> -
InputObject<T> -
InputPrimitive<T>
-
-
Unit function:
-
input<T>(input: unknown): Input<T>— type cast toInput<T>.
-
-
Basic validation functions:
-
stringInput(input: Input<string>): string | undefined -
numberInput(input: Input<number>): number | undefined -
booleanInput(input: Input<boolean>): boolean | undefined -
arrayInput<T>(input: Input<T[]>): Input<T>[] | undefined— checks that theinputis an array and returns it as an array of unvalidated elements. -
objectInput<T>(input: Input<T>): InputObject<T> | undefined— checks that theinputis a non-null, non-array object, and returns it as an object with unvalidated properties. -
nullInput(input: Input<null>): null | undefined.
-
Maybe chain to validate inputsimport { panic } from '@perfective/common/error';
import { maybe } from '@perfective/common/maybe';
import { isNatural, Natural } from '@perfective/common/number';
import { Input, InputObject, numberInput, objectInput } from '@perfective/common/object';
interface ExampleParams {
id: number;
}
interface Example {
params: ExampleParams;
}
function userId(request: Input<Example>): Natural {
return maybe(request) // (1)
.to<InputObject<Example>>(objectInput) // (2)
.pick('params')
.to<InputObject<ExampleParams>>(objectInput)
.pick('id')
.to(numberInput) // (3)
.otherwise(panic('User ID is not defined'))
.that(isNatural) // (4)
.or(panic('User ID is invalid'));
}-
requestmay beundefined. -
At the moment type transformations are not inferred correctly, so explicit type need to provided for
objectInput. -
Last validation of the input structure.
-
Final validation of the input, specific for the function.
|
Note
|
A custom validation monad may be added later to allow "collecting" all validation errors and warnings. |
-
Types:
-
Enum<T extends number | string>— AnObjectwith string keys and string or number values as generated by the TypeScript for anenumdefinition. -
Member<T extends number | string>— key of anenum. — Defines a type of the keys of anEnum.
-
-
Functions:
-
members<T extends number | string, E extends Enum<T>>(value: E): Member<T>[]— returns a list of anenumkeys.
-