我有一个类型保护检查函数,它确实告诉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中的上述所有内容:
1:为什么会这样?