简体   繁体   English

打字稿如何从类型中解包/删除 Promise?

[英]typescript how to unwrap/remove Promise from a type?

i have a function that accepts an object where each prop is a promise.我有一个函数,它接受一个对象,其中每个道具都是一个承诺。 it waits for all the promise to finish then returns a new object with the same props but now resolved values.它等待所有承诺完成,然后返回一个具有相同道具但现在已解析值的新对象。

在此处输入图片说明

resolved_props.company should be string , not Promise<string> resolved_props.company应该是string ,而不是Promise<string>

// TODO: fix the types on this
function promise_props<T>(obj:T):Promise<T> {
  const keys = Object.keys(obj)
  const len = keys.length
  const awaitables = new Array<T>(len)
  for (var i = 0; i < len; i++) awaitables[i] = (obj as any)[keys[i]]

  return Promise.all(awaitables).then((results) => {
    const byName:any = {}
    for (var i = 0; i < len; i++) byName[keys[i]] = results[i]
    return byName
  })
}

Your types are not accurate enough and the TypeScript compiler cannot figure it out that they are not promises at that point.您的类型不够准确,并且 TypeScript 编译器当时无法确定它们不是承诺。

What you need is something like this:你需要的是这样的:

async function promise_props<T>(obj: {[key: string]: Promise<T>}): Promise<{[key: string]: T}> {
    const keys = Object.keys(obj);
    const awaitables = keys.map(key => obj[key]);

    const values = await Promise.all(awaitables);
    const result: {[key: string]: T} = {};

    keys.forEach((key, i) => {
        result[key] = values[i];
    });
    return result;
}

But it will only work if your object has promises of the same type, for example:但它只有在您的对象具有相同类型的承诺时才有效,例如:

{
    company: Promise.resolve("company"),
    page: Promise.resolve("1")
};

I'm not sure if it is possible to get it working with various promise types in the current TypeScript version, but as Tao also suggested, you can use the new features in TypeScript 2.8 to get it working:我不确定是否可以在当前的 TypeScript 版本中使用各种承诺类型,但正如 Tao 还建议的那样,您可以使用 TypeScript 2.8 中的新功能来使其工作:

type UnPromisifiedObject<T> = {[k in keyof T]: UnPromisify<T[k]>}
type UnPromisify<T> = T extends Promise<infer U> ? U : T;

async function promise_props<T extends {[key: string]: Promise<any>}>(obj: T): Promise<UnPromisifiedObject<T>> {
    const keys = Object.keys(obj);
    const awaitables = keys.map(key => obj[key]);

    const values = await Promise.all(awaitables);
    const result = {} as any;

    keys.forEach((key, i) => {
        result[key] = values[i];
    });
    return result as UnPromisifiedObject<T>;
}

async function main() {
    const x = {
        company: Promise.resolve("company"),
        page: Promise.resolve(1)
    };
    const res = await promise_props(x);
    const company = res.company;  // company is a string here
    const page = res.page;        // page is a number here
}

As you can see, the return type is properly inferred.如您所见,正确推断了返回类型。 I think the implementation of the method can be improved.我认为该方法的实现可以改进。 I couldn't find a way to instantiate an instance of the return type and use any , but although compiler cannot infer it, it's type safe as we resolve all promises.我找不到实例化返回类型的实例并使用any ,但是尽管编译器无法推断它,但它是类型安全的,因为我们解决了所有承诺。

after typescript 2.8, i was able to use the following strategy在打字稿 2.8 之后,我能够使用以下策略

export type Await<T> = T extends Promise<infer U> ? U : T
export type AwaitProps<T> = {[P in keyof T]: Await<T[P]>}

export async function concurrent<T>(obj: T): Promise<AwaitProps<T>> {
    const keys = Object.keys(obj)
    const awaitables = keys.map(key => obj[key])
    const values = await Promise.all(awaitables)
    const result = {}
    keys.forEach((key, i) => result[key] = values[i])
    return <AwaitProps<T>>result
}

and the usage looks like this用法看起来像这样

const {claimRow, profileRow} = await concurrent({
    claimRow: claimTable.one(identify(userId)),
    profileRow: profileTable.one(identify(userId)),
})

Typescript 4.5打字稿 4.5

Awaited utility type is officially built in typescript v4.5. Awaited实用程序类型在 typescript v4.5 中正式构建。

https://devblogs.microsoft.com/typescript/announcing-typescript-4-5/#awaited-type https://devblogs.microsoft.com/typescript/annoucing-typescript-4-5/#awaited-type

// A = string
type A = Awaited<Promise<string>>;

// B = number
type B = Awaited<Promise<Promise<number>>>;

// C = boolean | number
type C = Awaited<boolean | Promise<number>>;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM