PromiseLike<T>类型是否存在问题?TypeScript Promise类型与运行时不符疑问
Promise.then无回调时的类型标注与运行时行为不一致问题
先看这段代码:
const p: Promise<number> = Promise.resolve(1); const q: Promise<string> = p.then<string>(); const r: string = await q; // 运行时实际结果:typeof r === 'number'
这里类型系统判定r是string,但实际运行后r却是number。而且.then<string>并不是类型断言,那这是不是TypeScript类型系统无法表达Promise无回调时真实运行时行为的情况?
先看TypeScript自带的PromiseLike接口定义(已翻译注释):
interface PromiseLike<T> { /** * 为Promise的决议或拒绝状态附加回调函数。 * @param onfulfilled Promise决议时执行的回调。 * @param onrejected Promise拒绝时执行的回调。 * @returns 一个新Promise,会在任意一个回调执行完成后决议。 */ then<TResult1 = T, TResult2 = never>( onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null ): PromiseLike<TResult1 | TResult2>; }
问题原因与结论
从类型定义能看出,then方法的泛型参数TResult1默认值是原Promise的类型T。当你显式指定TResult1为string时,类型系统会直接认为返回的Promise类型是Promise<string>(因为TResult2默认是never,string | never等价于string)。
但在运行时,根据Promise规范,如果then方法没有传入onfulfilled回调,新Promise会直接透传原Promise的决议值——也就是这里的1(number类型)。
这确实属于TypeScript类型系统的局限性:它的then方法类型定义没有区分「传入回调」和「未传入回调」两种场景的行为差异。当前的泛型逻辑默认只要指定了TResult1,就意味着回调会返回对应类型的值,但完全没考虑到未传回调时透传原值的运行时逻辑,无法在类型层面准确表达这种特殊情况。
内容的提问来源于stack exchange,提问作者Lucian Wischik
相关产品推荐
相关产品推荐

