Typescript 无法解析异步 then-catch 语句中的类型

问题描述 投票:0回答:1

我有以下代码,它是进行 API 调用和处理响应的简化版本。

type Result<TValue, TError> =
    | { ok: true, value: TValue}
    | { ok: false, msg: TError };

function sleep(ms: number) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function testRequest(): Promise<{success: true, data: number} | {success: false, msg: string}> {
    await sleep(1);

    const roll = Math.random();

    if (roll > 0.3) {
        return { success: true, data: 123 };
    } else if (roll > 0.6) {
        return { success: false, msg: 'hello world' };
    } else {
        throw new Error('value to high');
    }
}

async function runner(): Promise<Result<number, string>>{
    return await testRequest()
        .then( res => {
            if (res.success) {
                return { ok: true, value: res.data }
            } else {
                return { ok: false, msg: res.msg }
            }
        })
        .catch( error => {
            console.error('testRequest failed', { error });
            return { ok: false, msg:'request failed'}
        })
}

类型检查器在

return await testRequest()
行返回错误:

Type '{ ok: boolean; value: number; msg?: undefined; } | { ok: boolean; msg: string; value?: undefined; } | { status: string; msg: string; }' is not assignable to type 'Result<number, string>'.
  Type '{ ok: boolean; value: number; msg?: undefined; }' is not assignable to type 'Result<number, string>'.
    Type '{ ok: boolean; value: number; msg?: undefined; }' is not assignable to type '{ ok: false; msg: string; }'.
      Types of property 'ok' are incompatible.
        Type 'boolean' is not assignable to type 'false'.

Result
是成功和失败对象的联合,每个对象返回一个代表布尔值
status
和关联的
value
msg
键。

错误消息表明无法为类型

{ok: true, value: string}
返回
Result<number, string>
。然而,在
testRequest
中使用相同的模式没有任何问题?

我可以修复

runner()
哪些问题才能使其适用于成功|失败类型?

typescript asynchronous types async-await
1个回答
0
投票

一个简单的解决方案是将

Result
作为 const 返回,因为默认情况下该对象将具有 boolean 类型的属性
ok

.then( res => {
            if (res.success) {
                return { ok: true, value: res.data } as const
            } else {
                return { ok: false, msg: res.msg } as const
            }
})
// or
.then( res => {
            if (res.success) {
                return { ok: true as true, value: res.data } 
            } else {
                return { ok: false as false, msg: res.msg }
            }
})
© www.soinside.com 2019 - 2024. All rights reserved.