Data Models

HG data models are just TypeScript interfaces.

These interfaces should not have methods or any logic.

You can use data models on both client and server.

export interface UserListDTO {
    pageNumber ?: number;
    pageSize   ?: number;
    content     : readonly UserDTO[];
}

Builder functions

We recommend to create a builder function for your types.

It's much easier to extend your types later.

export function createUserListDTO (
    content     : readonly UserDTO[],
    pageNumber ?: number,
    pageSize   ?: number
) : UserListDTO {
    return {
        pageNumber,
        pageSize,
        content
    }
}

Type check functions

Type check functions are essential part of working with TypeScript.

HG provides advanced check functions for almost any type.

Your types should implement a check function beside them:

export function isUserListDTO (value: any): value is UserListDTO {
    return (
        isRegularObject(value)
        && hasNoOtherKeysInDevelopment(value, [
            'content',
            'pageSize',
            'pageNumber'
        ])
        && isArrayOf<UserDTO>(value?.content, isUserDTO)
        && isNumberOrUndefined(value?.pageSize)
        && isNumberOrUndefined(value?.pageNumber)
    );
}

Type explain functions

Sometimes you need to get a user-friendly description why a type check function doesn't accept your data.

You can add an explain function to do just that:

export function explainUserListDTO (value: any): string {
    return explain(
        [
            explainRegularObject(value),
            explainNoOtherKeysInDevelopment(value, [
                'content',
                'pageSize',
                'pageNumber'
            ]),
            explainProperty("content", explainArrayOf<UserDTO>("UserDTO", explainUserDTO, value?.content, isUserDTO)),
            explainProperty("pageSize", explainNumberOrUndefined(value?.pageSize)),
            explainProperty("pageNumber", explainNumberOrUndefined(value?.pageNumber))
        ]
    );
}

Parse functions

Parse functions can convert values from another format to your type.

It should be able to detect common data formats and turn them to your type.

For example, if the interface can be presented as a JSON string, and the input is a string, it should use parseJson().

Your parse function should never throw an exception. Instead, it should return undefined if the type is not correct.

export function parseUserListDTO (value: any) : UserListDTO | undefined {
    if (isString(value)) {
        value = parseJson(value);
    }
    return isParseUserListDTO(value) ? value : undefined;
}