我有一个类型保护检查函数,它告诉 JavaScript 一个值是否是一个承诺,同时它告诉 TypeScript 该变量是一个承诺:
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'
}
它工作得非常好,但是,我意识到我不需要硬编码 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
while 它应该是PlainObject | PlainObject[]
....
问题一:为什么会这样?
我尝试的更好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 中的所有内容: