TypeScript是否错误收窄了ReadableStreamDefaultReader.read()返回值的类型?
TypeScript是否错误收窄了ReadableStreamDefaultReader.read()返回值的类型?
你这个观察真的很细致!没错,这确实是TypeScript类型定义里存在的一个和实际行为不符的问题。
先看你贴的这段测试代码:
async function test(stream: ReadableStream<Uint8Array>) { const reader = stream.getReader() const { value, done } = await reader.read() // typeof value == Uint8Array<ArrayBufferLike> | undefined if (done) return // TypeScript推断此时typeof value == Uint8Array<ArrayBufferLike> }
按照TypeScript的类型收窄逻辑,当done为false时,它会认定value一定是有效的Uint8Array<ArrayBufferLike>实例,但实际运行场景里完全不是这样。
问题出在ReadableStreamDefaultController.enqueue()方法上,这个方法的chunk参数是可选的——你可以直接不带任何参数调用它:
controller.enqueue() // 没有传入chunk
实际测试就能发现,这种情况下调用reader.read()会返回{ value: undefined, done: false },但TypeScript的类型定义并没有覆盖这种场景,它错误地收窄了返回值的类型,默认只有当done为true时,value才可能是undefined。
本质上这是TypeScript的类型定义没有完全对齐标准的实际行为:标准里允许enqueue接收undefined作为chunk,对应的read()自然也可能在流未结束时返回undefined的value,但TypeScript的类型定义漏掉了这个细节。
内容来源于stack exchange




