打字稿:具有不同 return 类型的重载方法没有错误

Typescript: No error for overloaded methods with different return types

希望这个标题足以解释我要处理的情况!最近,我试图为一个方法创建一个接口,该方法可以接受 回调参数 return 一个承诺。这是为了避免将 Promise-based 模式引入到仅使用回调的代码库的遗留部分。

这是我定义的接口和该接口的实现的示例:

interface ITest {
    get(callback: () => void): void;

    get(): Promise<void>;
}


class Test implements ITest {
    public get(callback?: () => void): Promise<void> {
        if (typeof callback === 'function') {
            callback();
            return;
        }
        return Promise.resolve();
    }
}

这似乎有效,但是,有一种情况没有得到处理:

const t = new Test();
// Good
t.get(() => console.log('callback'));
// Good
t.get().then(() => console.log('then'));
// Bad - Exception
t.get(() => console.log('callback')).then(() => console.log('then'));

我希望在最后一个示例中,Typescript 会抱怨没有接受回调和 return 承诺的函数的签名。不过,如果我进行了以下调整,TypeScript 确实会抱怨:

const t: ITest = new Test();

经过这一更改,最后一个示例确实触发了 TSC 错误。我明白为什么会这样,因为我明确地说 t 正在实施 ITest。但是,我可以看到这是我很容易忘记做的事情。

所以,问题是:有没有更好的方法来完成我希望做的事情?

编辑: 很快就得到了答案,标记如下!如果您对 "compiled" class 的外观感兴趣,请使用该答案:

var Test = /** @class */ (function () {
    function Test() {
    }
    Test.prototype.get = function (callback) {
        if (typeof callback === 'function') {
            callback();
            return;
        }
        return Promise.resolve();
    };
    return Test;
}());

最后,我根本不知道 Typescript 会允许并删除该方法的那些额外声明。我可以看到需要在我的代码中添加一些额外的注释来向不熟悉的人解释 - 就像我刚才一样 - 为什么需要这些额外的声明。

您需要明确指定两个重载以获得您想要的错误类型。问题是,虽然 class 中的 get 方法在检查 class 中函数的签名时确实在接口中实现了该方法(它满足它的约束)。您可以明确指定这两个重载,并且实现签名(当前存在的那个)将对外部隐藏。

interface ITest {
    get(callback: () => void): void;

    get(): Promise<void>;
}


class Test implements ITest {

    public get(callback: () => void): void;
    public get(): Promise<void>;
    public get(callback?: () => void): Promise<void> {
        if (typeof callback === 'function') {
            callback();
            return;
        }
        return Promise.resolve();
    }
}

const t = new Test();
// Good
t.get(() => console.log('callback'));
// Good
t.get().then(() => console.log('then'));
// Compile time error
t.get(() => console.log('callback')).then(() => console.log('then'));