首页 > 解决方案 > 在 Typescript 中,为什么函数重载顺序仅在重载函数作为参数传递时才重要?

问题描述

当一个函数被重载并作为参数传递给一个函数时,它似乎不保持重载,只选择最后一个定义。

我验证了定义顺序很重要并创建了一个最小的示例:Playground 链接

function call<U extends object, V>(method: Api<U, V>, params: U): Promise<V> {
    return new Promise((res) => {
        method(params, (err, resp) => {
            return resp;
        })
    });
}

type Api<U, V> = (params: U, callback: (err: {}, resp: V) => void) => void;

/** Signature (1) */
function apiMethod(params: {id: number}, callback: (err: {}, resp: {lol: number}) => void): void;
/** Signature (2) */
function apiMethod(callback: (err: {}, resp: {lol: number}) => void): void;
function apiMethod(
    paramsOrCallback: {id: number} | ((err: {}, resp: {lol: number}) => void), 
    callback?: (err: {}, resp: {lol: number}) => void
) {
    if (callback) {
        callback({}, {lol: 1234567});
    }
    if (typeof paramsOrCallback === 'function') {
        paramsOrCallback({}, {lol: 1234567});
    }
}

// If signature (1) before signature (2) then this is a type error
// If you move signature (2) before signature (1) then this is allowed
const r = call(apiMethod, {id: 3});

// This is using signature (1) and is working well
apiMethod({id: 123}, () => {});
// This is using signature (2) and is working well
apiMethod(() => {});

我希望这个示例能够独立于签名 (1) 和签名 (2) 的顺序进行编译和正常工作。

似乎 TS 编译器在传递函数时决定了哪个函数定义,并且由于某种原因总是选择最后一个定义。

我想澄清为什么会发生这种情况(并建议阅读有关函数重载内部的材料)以及如何修复丰富函数的类型call以使其独立于签名(1)和(2)顺序工作.

标签: typescriptgenericsoverloading

解决方案


推荐阅读