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

时间:2018-05-22 12:25:52

标签: typescript typescript-types

希望这个标题足以说明我试图处理的情况!最近,我试图为一个方法创建一个接口,该方法可以 一个回调参数返回一个promise。这是为了处理不将基于Promise的模式引入仅使用回调的代码库的遗留部分。

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

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会抱怨函数的签名没有回调并返回一个承诺。但是,如果我在下面进行调整,那么TypeScript就会抱怨:

const t: ITest = new Test();

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

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

编辑:很快得到了答案,标记如下!如果你对&#34;编译的内容感兴趣&#34; class看起来像使用那个答案:

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

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

1 个答案:

答案 0 :(得分:3)

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

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