能够将不同的参数签名作为函数参数传递

时间:2018-11-26 20:35:33

标签: javascript node.js typescript

我有两个函数article.getByCustomerAndCategory(需要两个参数)和article.getById(需要一个参数)。

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');
};

也尝试过:

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');
};

我希望将两者结合成一个函数,可以采用customer_idcategory_id或仅采用article_id。返回类型都相同。

1 个答案:

答案 0 :(得分:1)

您的方法距离不太远。使用联合表示可以传递给函数的两种参数是一个好主意。您缺少的部分是类型防护,可以将input参数的类型缩小为其中一个并集成员:

// 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');
};