export type {{value_type_name}} = {
    {%- for field_name, field_typedef in field_typedefs %}
    {{field_name}}: {{field_typedef.value_type_name}};
    {%- endfor %}
};

export type {{data_type_name}} = {
    {%- for field_name, field_typedef in field_typedefs %}
    {{field_name}}: {{field_typedef.data_type_name}};
    {%- endfor %}
};

export function {{to_data_name}}(value: {{value_type_name}}): {{data_type_name}} {
    return {
        {%- for field_name, field_typedef in field_typedefs %}
        {{field_name}}: {{field_typedef.to_data_name}}(value.{{field_name}}),
        {%- endfor %}
    };
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function {{from_data_name}}(data: any): {{value_type_name}} {
    if (
        typeof data !== "object"
        || Array.isArray(data)
        || data === null
    ) {
        {{RAISE_DESERIALIZATION_ERROR}};
    }
    const dataObj: object = data;

    {%- for field_name, field_typedef in field_typedefs %}

    if (!Object.hasOwn(dataObj, "{{field_name}}")) {
        {{RAISE_DESERIALIZATION_ERROR}};
    }
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const fieldData__{{field_name}} = (dataObj as {{"{"}}{{field_name}}: any})["{{field_name}}"];
    const fieldValue__{{field_name}} = {{field_typedef.from_data_name}}(fieldData__{{field_name}});
    {%- endfor %}

    return {
        {%- for field_name, field_typedef in field_typedefs %}
        {{field_name}}: fieldValue__{{field_name}},
        {%- endfor %}
    };
}