Create, hydrate and validate

Bored of creating objects by hand? Factories to the rescue!

About 4 minutes length

BlogCreate, hydrate and validate

This is a small one.

When you have a type T (which maybe represents an object), you will of course need a way to build, hydrate and validate an instance of T.

You could do everything by hand, but it's not really a good idea: the type could change or you could risk to bloat your code or whatever.

Here's the simplest but deadly efficient way of creating a factory which creates and hydrates and object's instance.

export interface MyObject {
readonly myprop1: string;
readonly myprop2: number[];
readonly myprop3: { [index: string]: number[] };
readonly myprop4: Date;
}
//#region factories
export const create = (partial: Partial<MyObject> = {}): MyObject => ({
myprop1: partial.myprop1 ?? ``,
myprop2: [... partial.myprop2],
myprop3: { ... partial.myprop3 },
myprop4: partial.myprop4 ?? new Date(),
})
//#endregion

This way, you will be able to both create and hydrate your type T.

The biggest issue comes with validation.

To add it, I'll create a typeguard using a library called tiinvo

import { anyof, check, isfunction, isstring, implementing, isarrayof, isnumber, isindexable, haskeyoftype } from 'tiinvo'
export interface MyObject {
readonly myprop1: string;
readonly myprop2: number[];
readonly myprop3: { [index: string]: number[] };
readonly myprop4: Date;
}
//#region typeguards
export const isMyObject = implementing<MyObject>({
myprop1: isstring,
myprop2: isarrayof(isstring),
myprop3: isindexable,
myprop4: anyof(
haskeyoftype('getDate', isfunction),
haskeyoftype('getFullYear', isfunction),
haskeyoftype('getMonth', isfunction),
),
});
//#endregion
//#region factories
export const create = (partial: Partial<MyObject> = {}): MyObject => ({
myprop1: partial.myprop1 ? check(isstring(partial.myprop1), 'myprop1 is not a string')(partial.myprop1) ``,
myprop2: partial.myprop2 ? isarrayof(isnumber)(partial.myprop2) [... partial.myprop2],
myprop3: { ... partial.myprop3 },
myprop4: partial.myprop4 ?? new Date(),
})
//#endregion

Doing this way, we could import the module and with enough safety we could create and/or validate a type T

import * as TMyObject from 'types/MyObject';
const t1 = TMyObject.create()
const t2 = TMyObject.create({ myprop1: 'name' })
TMyObject.isMyObject(t1) // true
TMyObject.isMyObject(t2) // true
TMyObject.isMyObject({}) // false

Other blog posts: