微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Typescript-具有不同返回值的Promise动态数组

如何解决Typescript-具有不同返回值的Promise动态数组

有人可以帮助我解决代码的问题吗? 我找不到在底部Promise.all调用中插入的正确类型。 它也尝试了Promise.all<Services[],PullRequests[]>(ops),但是PullRequests[]不能是可选的...

function wait<Twait>(time: number,response: Twait): Promise<Twait> {
    return new Promise(resolve => setTimeout(() => resolve(response),time))
}

interface Service {
    name: string;
    id: number;
}

async function getServices(): Promise<Service[]>  {
    const response = await wait(400,{ "id": 200 });
    return [{ name: "service",id: response.id }]
}


interface PullRequest {
    prType: string;
    githubId: number;
}

async function getPrs(): Promise<PullRequest[]>  {
    const response = await wait(400,{ "githubId": 200 });
    return [{ prType: "foo",githubId: response.githubId }]
}


async function main(): Promise<void> {

    const ops: [ PromiseLike<Service[]>,PromiseLike<PullRequest[]>? ] = [getServices()]

    if (Math.random() > 0.5) { // <== this is random on purpose.
        ops.push(getPrs())
    }
    
    
    const [ services,prs ] = await Promise.all(ops) // This throws a ts compile error (attached below)
    console.log("services:")
    console.log(services)
    console.log("prs:")
    console.log(prs)    
}

No overload matches this call. The last overload gave the following error.
 Argument of type '[PromiseLike<Service[]>,(PromiseLike<PullRequest[]> | undefined)?]' is not assignable to parameter of type 'Iterable<Service[] | PromiseLike<Service[] | undefined> | undefined>'. 
The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types. 
Type 'IteratorResult<PromiseLike<Service[]> | PromiseLike<PullRequest[]> | undefined,any>' is not assignable to type 'IteratorResult<Service[] | PromiseLike<Service[] | undefined> | undefined,any>'. 
Type 'IteratorYieldResult<PromiseLike<Service[]> | PromiseLike<PullRequest[]> | undefined>' is not assignable to type 'IteratorResult<Service[] | PromiseLike<Service[] | undefined> | undefined,any>'. 
Type 'IteratorYieldResult<PromiseLike<Service[]> | PromiseLike<PullRequest[]> | undefined>' is not assignable to type 'IteratorYieldResult<Service[] | PromiseLike<Service[] | undefined> | undefined>'. 
Type 'PromiseLike<Service[]> | PromiseLike<PullRequest[]> | undefined' is not assignable to type 'Service[] | PromiseLike<Service[] | undefined> | undefined'. 
Type 'PromiseLike<PullRequest[]>' is not assignable to type 'Service[] | PromiseLike<Service[] | undefined> | undefined'. 
Type 'PromiseLike<PullRequest[]>' is not assignable to type 'PromiseLike<Service[] | undefined>'. 
Type 'PullRequest[]' is not assignable to type 'Service[]'. 
Type 'PullRequest' is missing the following properties from type 'Service': name,id

解决方法

根据microsoft/TypeScript#28427,这看起来像TS库定义中的已知问题。当前,该库对一堆不包含可选元素的特定元组类型进行硬编码。已经进行了一些努力来解决此问题,但是显然PromiseLike类型及其与await的交互非常复杂,以至于尚未接受解决此问题的请求。 A comment in microsoft/TypeScript#39788解释说,对此进行切换可能会破坏依赖于当前定义的现有真实世界代码。

直到,除非得到上游解决,否则您可以使用declaration mergingPromise.all()添加您自己的签名,该签名只是maps可以在传入数组的元素上展开承诺-或元组:

interface PromiseConstructor {
  all<T extends readonly any[]>(
    values: { [K in keyof T]: T[K] | PromiseLike<T[K]> }
  ): Promise<T>;
}

您可以测试它是否可以满足您的要求:

const promiseAllOps = Promise.all(ops); // no error now  
// const promiseAllOps: Promise<[Service[],(PullRequest[] | undefined)?]>
const awaitPromiseAllOps = await promiseAllOps;
// const awaitPromiseAllOps: [Service[],(PullRequest[] | undefined)?]
const [services,prs] = awaitPromiseAllOps;
services; // Service[]
prs; // PullRequest[] | undefined

Playground link

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。