Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

129
Views
JS TS how to refactor repetitive code into a higher order function with multiple param types

I've been wanting to refactor the following code into a higher order function with typescript to make it cleaner and more re-usable, though have been finding it really challenging to make it work.

import { DocumentDefinition, FilterQuery, QueryOptions, UpdateQuery } from 'mongoose';
import TaskModel, { TaskDocument } from '../models/Task.model';
import { databaseResponseTimeHistogram } from '../utils/appmetrics';

export async function createTask(
    input: DocumentDefinition<
        Omit<TaskDocument, 'createdAt' | 'updatedAt' | 'taskId' | 'isCompleted'>
    >
) {
    const metricsLabels = { operation: 'createTask' };
    const timer = databaseResponseTimeHistogram.startTimer();

    try {
        const result = TaskModel.create(input);
        timer({ ...metricsLabels, success: 'true' });

        return result;
    } catch (err: any) {
        timer({ ...metricsLabels, success: 'false' });
        throw new Error(err.message);
    }
}

export async function findTask(
    query: FilterQuery<TaskDocument>,
    options: QueryOptions = { lean: true }
) {
    const metricsLabels = { operation: 'findTask' };
    const timer = databaseResponseTimeHistogram.startTimer();

    try {
        const result = TaskModel.findOne(query, {}, options);
        timer({ ...metricsLabels, success: 'true' });

        return result;
    } catch (err: any) {
        timer({ ...metricsLabels, success: 'false' });
        throw new Error(err.message);
    }
}

export async function findAndUpdateTask(
    query: FilterQuery<TaskDocument>,
    update: UpdateQuery<TaskDocument>,
    options: QueryOptions
) {
    const metricsLabels = { operation: 'findTask' };
    const timer = databaseResponseTimeHistogram.startTimer();

    try {
        const result = TaskModel.findOneAndUpdate(query, update, options);
        timer({ ...metricsLabels, success: 'true' });

        return result;
    } catch (err: any) {
        timer({ ...metricsLabels, success: 'false' });
        throw new Error(err.message);
    }
}

Basically I am wanting to refactor the whole metrics functionality with the try catch block into a utility function, allowing to call it with the respective parameters, the operation, the TaskModel.method and corresponding params with would be (input) for create, (query, {}, options) for findOne and (query, update, options) for findManyAndUpdate...

So far have I ran into difficulties with correct typing of all the different params etc.

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

So basically you want to refactor this part:

try {
    /* SOME OPERATION */
    timer({ ...metricsLabels, success: 'true' });

    return result;
} catch (err: any) {
    timer({ ...metricsLabels, success: 'false' });
    throw new Error(err.message);
}

You can just wrap it in a function and pass in the SOME OPERATION as an argument:

function withTimer (label:string, operation:Function) {
    const metricsLabels = { operation: label };
    const timer = databaseResponseTimeHistogram.startTimer();

    try {
        const result = operation();
        timer({ ...metricsLabels, success: 'true' });

        return result;
    } catch (err: any) {
        timer({ ...metricsLabels, success: 'false' });
        throw new Error(err.message);
    }
}

Now your functions can be rewritten as:

export async function createTask(
    input: DocumentDefinition<
        Omit<TaskDocument, 'createdAt' | 'updatedAt' | 'taskId' | 'isCompleted'>
    >
) {
    return withTimer('createTask',
        () => TaskModel.create(input)
    );
}

export async function findTask(
    query: FilterQuery<TaskDocument>,
    options: QueryOptions = { lean: true }
) {
    return withTimer('findTask',
        () => TaskModel.findOne(query, {}, options)
    );
}

export async function findAndUpdateTask(
    query: FilterQuery<TaskDocument>,
    update: UpdateQuery<TaskDocument>,
    options: QueryOptions
) {
    return withTimer('findTask',
        () => TaskModel.findOneAndUpdate(query, update, options)
    );
}

The key to using higher-order functions is realizing that you can wrap the uncommon parts of code in functions to be passed to the common parts of code.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!