TypeScript中Promise resolve类型收窄的赋值合法性疑问
TypeScript中Deferred类的resolve赋值合法性解析
先看对应的代码示例:
class Deferred<T> { promise: Promise<T>; resolve!: (value: T) => void; reject!: (reason?: any) => void; constructor() { this.promise = new Promise<T>((resolve, reject) => { this.resolve = resolve; this.reject = reject; }); } }
疑问点
Promise构造器的resolve参数类型是(value: T | PromiseLike<T>) => void,但类中resolve字段的类型仅为(value: T) => void,看似是把接受更宽泛类型的函数赋值给了接受更窄类型的函数,却能通过TypeScript编译,原因是什么?
核心原因:函数参数的逆变特性
TypeScript判断函数类型兼容性时,遵循参数逆变、返回值协变的规则:
- 返回值协变:若目标函数的返回值类型是源函数返回值类型的子类型,赋值合法。
- 参数逆变:若源函数的参数类型是目标函数参数类型的超类型(即目标参数类型更具体),赋值合法。
放到这个场景中:
- 源函数(Promise构造器的resolve)的参数类型是
T | PromiseLike<T>,这是T的超类型(T是T | PromiseLike<T>的子集)。 - 目标函数(
this.resolve)的参数类型是T,比源函数的参数类型更具体。
根据参数逆变规则,这种赋值完全合法:当外部调用this.resolve时,只能传入T类型的值,而该值完全符合源函数(Promise resolve)的参数要求(T属于T | PromiseLike<T>的范畴),不会出现类型不兼容的问题。
额外说明
这种写法是合理的封装:Deferred类对外暴露的resolve接口只接受T类型,隐藏了Promise原生resolve支持PromiseLike<T>的细节,但内部实现完全兼容,既保证了类型安全,又实现了Deferred的功能。
内容的提问来源于stack exchange,提问作者chinabuffet
相关产品推荐
相关产品推荐

