Reputation: 59355
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
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