在打字稿中返回有效载荷为T时如何推断正确的类型?

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

我有一个类型保护检查函数,它确实告诉JavaScript值是否是一个Promise,同时它告诉TypeScript变量是一个Promise:

function getType (payload: any): string {
  return Object.prototype.toString.call(payload).slice(8, -1)
}    

function isPromise (payload: any): payload is Promise<any> {
  return getType(payload) === 'Promise'
}

它确实很好,但是,我意识到我不需要对承诺解析为any进行硬编码,而是推断出该类型。

此示例为何我看到any无法正常工作:

export type PlainObject = { [key: string]: any }
let a: PlainObject | PlainObject[] | Promise<PlainObject | PlainObject[]>
let b = isPromise(a) ? await a : a

在此示例中,将b推断为PlainObject,而应将其设为PlainObject | PlainObject[]...。

问题1:为什么会这样?

我尝试使用更好的isPromise功能的解决方案:

type Unpacked<T> =
    T extends (infer U)[] ? U :
    T extends (...args: any[]) => infer U ? U :
    T extends Promise<infer U> ? U :
    T;

function isPromise2 <T extends any>(payload: T): payload is Promise<Unpacked<T>> {
  return getType(payload) === 'Promise'
}

理论上,我不明白为什么这行不通。但是我得到这个错误:

类型谓词的类型必须可分配给其参数的类型。类型“ Promise>”不能分配给类型“ T”。'Promise>'可分配给类型'T'的约束,但是'T'可以用约束'any'的不同子类型实例化]

问题2: payload is Promise<Unpacked<T>>为什么不起作用,并且我该如何推断呢?

这里是TypeScript PlayGround中的上述所有内容:

https://www.typescriptlang.org/v2/en/play?#code/KYDwDg9gTgLgBDAnmYcAKAbAhgSwHYDyARgFbADG8AvHAN5wDaA1sIgFxwDOMU+A5gF0OWPIjgBfAFCSAZgFc8lHBDxw+wGABVkqABRgsiDBCwATYaICUHbrzx86kuHCga5UVcTKUAdGCgQMIE6PkEAyjz8PuRYGBj6hsZmlj6cGDjkwLoAHAA0cAC0AIyWkuLOztLyijDKqjicaAEAtg16BkYm5nAiiNZwHUmmcA3oLW0APL0AfI7OrjDuqupaOgmdyXBU23AA5E0QrZzAu2XSGBo9HJi4hKQU8AA+6Nj4Xg8MAnDPB0fAEzc3vdKN8Xrd3pRPtNJBd4EQtiNGuNjrosJY4AB+HoAd1w8CwcGE0gA9MS4NiABZYeAASRcwFiGDEuLw8CCcFMEERbEkSBQcAAqngDOQWKYJppZlQnBVNHBQDBgHhTJw4Lp8DJgFBBZZPpjBYSZc45QqlSq1T5LVgoHxOBZEJ90VRZhqtQasQLDRU4CaQIrlarfpNXdqBbMPV7ZQBuKoKJQqRFB44AJjgEvlfrNqpm6yGHE0-UGXURY0OkyFIrFEums1oMoWSzUGm0KFzXSdO32yJOZyAA

typescript casting type-inference typeguards
1个回答
0
投票

1:为什么会这样?

© www.soinside.com 2019 - 2024. All rights reserved.