objection.js icon indicating copy to clipboard operation
objection.js copied to clipboard

What is the best way to type a model with relations?

Open anthonyma94 opened this issue 3 years ago • 0 comments

I have a model like this, with the corresponding interface:

export default class CIProject extends BaseEntity implements ICIProject {
    static tableName = TableNames.CI_PROJECT;

    id: number;
    projectNumber?: number;
    projectName: string;
    owner: string;
    status: number;
    projectDueDate: Dayjs;
    completedDate?: Dayjs;
    createdAt: Dayjs;

    static relationMappings = () => {
        return {
            tasksRelationship: {
                relation: Model.HasManyRelation,
                modelClass: CIProjectTask,
                join: {
                    from: `${TableNames.CI_PROJECT}.id`,
                    to: `${TableNames.CI_PROJECT_TASK}.project_id`,
                },
            },
        };
    };
}

export interface ICIProject {
    id: number;
    projectNumber?: number;
    projectName: string;
    owner: string;
    status: number;
    projectDueDate: Dayjs;
    completedDate?: Dayjs;
    createdAt: Dayjs;
    tasksRelationship?: ICIProjectTask[];
}

For tasksRelationship, I'd like to make it required when returning a query with withGraphJoined("tasksRelationship"), but I'd have to typecast the result to unknown first:

type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };

const res = (await CIProject.query().withGraphJoined(
  "tasksRelationship"
)) as unknown as Array<WithRequired<ICIProject, "tasksRelationship">>;

If I don't typecast it to unknown first, it gives me the following error: Property 'tasksRelationship' is missing in type 'CIProject' but required in type '{ tasksRelationship: ICIProjectTask[]; }'.

Is there a better way of doing this, so I don't have to typecast it to unknown first?

anthonyma94 avatar Mar 23 '22 17:03 anthonyma94