如何解除对象中的承诺类型?

时间:2018-02-07 02:48:37

标签: typescript variadic-templates

假设我有一个函数接收一个值为promise的对象并等待所有promises解析,如下所示:

function aggregatePromiseValues<T>(promiseObject: { [key: string]: Promise<T> }) {
    /* the type is *NOT* correct */

    const promises = [];
    const result = {};
    for (let key in promiseObject) {
        const valuePromise = promiseObject[key];
        promises.push(valuePromise.then(value => result[key] = value));
    }
    return Promise.all(promises).then(() => result);
}

const arg = {
    a: Promise.resolve(1),
    b: Promise.resolve('hello')
};
type resultType = Promise<{
    a: number,
    b: string
}>;

const result: resultType = aggregatePromiseValues(arg); // <--- error here

如何编写函数aggregatePromiseValues的类型,以便它可以根据参数的类型返回正确的类型?

1 个答案:

答案 0 :(得分:1)

您可以使用映射类型作为参数和结果:

function aggregatePromiseValues<T>(promiseObject: {[key in keyof T]: Promise<T[key]>}){

    const promises = [];
    const result = {} as {[key in keyof T]: T[key]};
    for (let key in promiseObject) {
        const valuePromise = promiseObject[key];
        promises.push(valuePromise.then(value => result[key] = value));
    }
    return Promise.all(promises).then(() => result);
}

const arg = {
    a: Promise.resolve(1),
    b: Promise.resolve('hello')
};

const result = aggregatePromiseValues(arg); 

结果类型被正确推断为Promise<{ a: number; b: string; }>,您无需明确键入。

在函数内部,您必须使用类型断言

初始化结果
    const result = {} as {[key in keyof T]: T[key]};

因为没有它,TypeScript将不允许使用空对象初始化它。如果你试试

const result: {[key in keyof T]: T[key]} = {};

您收到错误Type '{}' is not assignable to type '{[key in keyof T]: T[key];}'.

请注意,您可以将{[key in keyof T]: T[key]}简化为T

const result = {} as T;

所以你没有真正“提升”类型的承诺,你采用正常的,“未经证实的”类型T并使用promisified属性创建新的映射类型,以用作{{1}参数类型。