打字稿:在承诺上缩小类型

时间:2017-09-19 14:12:16

标签: javascript typescript promise

我正在试图弄清楚如何根据参数在promises上使用typeguards。

function request({ logic }: { logic: boolean }) {
    return new Promise((resolve, reject) => {
        if (l)
            resolve("something");
        resolve(1);
    });
}

request({ logic: true }).then(a => {
    a.length
})

在这个例子中,我想确保'a'=='字符串'的类型。我尝试在request中编写一些类型保护措施,但结果却丢失了。我不知道这只是打字稿的限制,还是我只需要做一些智能型铸造或什么。

这是我实际尝试做的一个玩具示例,即进行异步调用,其结果根据某些参数略有不同。而且我不愿意做另一个功能只是为了覆盖一个改变的返回类型

2 个答案:

答案 0 :(得分:3)

打字稿函数重载到救援:

function request(logic: true): Promise<string>;
function request(logic: false): Promise<number>;
function request(logic: boolean) {
    return new Promise((resolve, reject) => {
        if (logic) 
            resolve("something");
        resolve(1);
    });
}

request(true).then(a => {
    console.log(a.length); //<-- knows that a is a string
});

request(false).then(a => {
    console.log(a.length); //<-- error: prop 'length' does not exist on number
});

Typeguards旨在用于if语句。

修改

你会感到惊讶! Typescript也支持基于字段的重载区别!请检查以下代码:

function request(opts: { logic: true }): Promise<string>;
function request(opts: { logic: false }): Promise<number>;
function request(opts: { logic: boolean }) {
    return new Promise((resolve, reject) => {
        if (opts.logic) 
            resolve("something");
        resolve(1);
    });
}


request({ logic: true }).then(a => {
    console.log(a.length); //<-- knows that a is a string
});

request({ logic: false }).then(a => {
    console.log(a.length); //<-- error: prop length cannot be found on type number
});

编辑

通过一点通用魔法,您可以实现所需的行为。这样,只有logic字段才能从调用者的角度出发。缺点是,即使opts.logic函数实现中的request,您也会失去类型检查。

function request<T extends { logic: true }>(opts: T): Promise<string>;
function request<T extends { logic: false }>(opts: T): Promise<number>;
function request(opts: any) {
    return new Promise((resolve, reject) => {
        if (opts.logic) 
            resolve("something");
        resolve(1);
        console.log(opts.anything);
    });
}

request({ logic: true, foo: 'bar' }).then(a => {
    console.log(a.length); //<-- knows that a is a string
});

request({ logic: false, foo: 'baz' }).then(a => {
    console.log(a.length); //<-- error: prop length cannot be found on type number
});

答案 1 :(得分:-1)

下一个是正确的重载(应该添加类型):

function request(logic: boolean): Promise<string>;
function request(logic: boolean): Promise<number>;
function request(logic: boolean): Promise<any>;
function request(logic: boolean) {
    return new Promise((resolve, reject) => {
        if (logic) 
            resolve("something");
        resolve(1);
    });
}

request(true).then((a) => {
    console.log(a.length); //<-- knows that a is a string
});

request(false).then((a) => {
    console.log(a.length); //<-- error: prop 'length' does not exist on number
});