ThomasReggi
ThomasReggi

Reputation: 59355

Ability to pass different argument signatures as function arguments

I have two functions article.getByCustomerAndCategory (that takes two parameters) and article.getById (that takes one).

function  getArticle ({ customer_id, category_id, article_id }: Partial<Article>): Article {
    if (customer_id && category_id) {
        return article.getByCustomerAndCategory({
            customer_id,
            category_id,
        });
    }
    if (article_id) {
        return article.getById({
            article_id
        });
    }
    throw new Error('invalid argument');
};

Also tried:

type articleInput = { customer_id, category_id } | { article_id };

function  getArticle (input: articleInput): Article {
    if (input.customer_id && input.category_id) {
        return serviceRecurrence.get({
            customer_id,
            category_id,
        });
    }
    if (input.article_id) {
        return serviceRecurrence.getById({
            article_id
        });
    }
    throw new Error('invalid argument');
};

I am looking to combine the two into one function that can take either customer_id and category_id or just article_id. The return types are all the same.

Upvotes: 1

Views: 41

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249546

Your approach was not too far off. Using a union to represent the two kinds of parameters that can be passed to the function is a good idea. The part you are missing is a type guard to narrow the type of the input parameter to one of the union members:

// Assumed declarations  Types
interface Article {
    customer_id: number, category_id: number
}
let serviceRecurrence: {
    get(p: {
        customer_id: number, category_id: number
    }): Article
    getById(p: {
        article_id: number
    }): Article
}
type articleInput = { customer_id: number, category_id: number } | { article_id: number };

// The function 
function  getArticle (input: articleInput): Article {
    if ('article_id' in input) { // in typeguard
        return serviceRecurrence.getById({
            ... input // input is { article_id: number } and we can use a spread operator to create the input for getById
        });
    }
    else  {
        return serviceRecurrence.get({
            ... input // input is { customer_id: number, category_id: number } and we can use a spread operator to create the input for get
        });
    }
    throw new Error('invalid argument');
};

Upvotes: 1

Related Questions